CircuitPython中Asyncio无法并发运行两个函数的问题求助
CircuitPython(树莓派Pico)Asyncio并发失效问题修复
问题背景
我在树莓派Pico的CircuitPython环境下开发项目,需要用Asyncio实现函数并发,但运行后并发没生效——输出先出现audio,过一会儿才出现LCD。我知道需要用await但不知道怎么正确应用,已经通过Circup在Windows 11上装好Asyncio库,程序概要如下:
async def playAudio(import1, import2): # 相关操作 print("audio") # 调试打印 if 音频未播放完成: playAudio() async def lcdScreen(import1, import2): print("LCD") # 调试打印 # 相关操作 lcd.print("*something*") time.sleep(1) lcd.print("*something else*") time.sleep(1) async def story(相关参数): L = await asyncio.gather( playAudio(参数), playAudio(参数), ) print(L) while True: # 前置操作 asyncio.run(story(*所有参数))
问题原因及修复方法
代码里有几个核心问题导致并发失效:
同步sleep阻塞事件循环
lcdScreen里的time.sleep(1)是同步阻塞函数,会直接停掉整个Asyncio事件循环,其他协程根本没机会运行。必须换成Asyncio的异步睡眠:await asyncio.sleep(1)协程调用未加await
playAudio里递归调用自己时没加await,这会让协程脱离事件循环调度,无法正确执行。要改成await playAudio(import1, import2)未将LCD任务加入并发列表
你在story里只启动了两个playAudio协程,lcdScreen根本没被放进asyncio.gather里并发执行——这就是LCD输出延迟的核心原因。必须把lcdScreen也加入gather的任务列表。循环中重复调用asyncio.run
在同步的while True里反复调用asyncio.run()会重复创建事件循环,CircuitPython的Asyncio对这种情况支持不好。应该把循环逻辑放到异步主协程里。
修复后的示例代码
import asyncio # 导入你的LCD、音频相关库 async def playAudio(import1, import2): # 音频播放操作 print("audio") # 假设这里有判断音频是否播放完成的逻辑 if not audio_finished: await playAudio(import1, import2) # 必须加await async def lcdScreen(import1, import2): print("LCD") # LCD初始化等操作 lcd.print("*something*") await asyncio.sleep(1) # 替换成异步sleep lcd.print("*something else*") await asyncio.sleep(1) async def main(all_args): while True: # 原来while True里的前置操作 await asyncio.gather( playAudio(*all_args), lcdScreen(*all_args) # 加入LCD并发任务 ) # 启动主协程 asyncio.run(main(all_args))
核心注意事项
- 协程里的所有阻塞操作(等待、IO)都要用Asyncio提供的异步版本,不能用同步函数
- 调用任何协程都必须加
await,否则协程不会被事件循环调度执行 - 用
asyncio.gather集中管理需要并发的所有协程,确保它们同时被调度 - 不要在同步循环里反复创建事件循环,用异步主协程管理整个程序的循环逻辑
内容的提问来源于stack exchange,提问作者Z1scko
相关产品推荐
相关产品推荐

