拆分AioRTC数据通道至多线程时遇协程未等待错误求助
问题解决:
coroutine 'updatePTZReadOut' was never awaited 错误分析与修复 核心问题点
- 未正确await异步操作:
asyncio.sleep(0.5)未加await,导致协程对象未被执行,触发警告 - 事件循环设置逻辑错误:
asyncio.set_event_loop()返回None,导致后续loop变量无效 - 协程启动方式矛盾:用
run_until_complete启动无限循环协程后,再调用run_forever完全多余 - 同步操作阻塞事件循环:数据库查询、
readPTZCoords等同步代码会卡住async事件循环 - DataChannel创建时机不合理:未考虑WebRTC连接状态,直接创建通道可能导致发送失败
分步修复方案
1. 调整协程启动逻辑
不需要用run_until_complete启动无限循环协程,直接将协程作为任务加入事件循环后启动即可:
ptzcoords = 'Supported' #PTZ Coords will be part of WebRTC Communication, send every 0.5 seconds. def start_ptz_loop(webRtcPeer, cameraName): ptzloop = asyncio.new_event_loop() asyncio.set_event_loop(ptzloop) # 将协程作为任务加入事件循环 ptzloop.create_task(updatePTZReadOut(webRtcPeer, cameraName)) ptzloop.run_forever() # 启动线程运行事件循环 ptzUpdateThread = Thread(target=start_ptz_loop, args=(webRtcPeer, cameraName)) ptzUpdateThread.start()
2. 修正updatePTZReadOut协程
修复await问题、同步操作阻塞问题,调整DataChannel就绪逻辑:
async def updatePTZReadOut(rtcPeer, cameraName): loop = asyncio.get_running_loop() # 用线程池执行同步数据库查询,避免阻塞事件循环 def get_camera_data(): # 用参数化查询避免SQL注入 myCursor.execute("Select * from localcameras where name = %s", (cameraName,)) camtuple = myCursor.fetchall() return camtuple[0] camdata = await loop.run_in_executor(None, get_camera_data) # 创建DataChannel并等待通道就绪 channel_local = rtcPeer.createDataChannel("chat") # 等待通道打开(适配多数WebRTC库的事件监听方式) channel_open = asyncio.Event() def on_open(): channel_open.set() channel_local.on("open", on_open) await channel_open.wait() while True: # 用线程池执行同步PTZ坐标读取 ptzcoords = await loop.run_in_executor( None, readPTZCoords, camdata[1], camdata[3], cryptocode.decrypt(str(camdata[4]), passwordRandomKey) ) print("Updating Coords to {0}".format(ptzcoords)) # 发送坐标数据 await channel_local.send(str(ptzcoords)) # 必须await异步sleep await asyncio.sleep(0.5)
3. 额外注意事项
- 线程安全:WebRTC PeerConnection通常不是线程安全的,如果
rtcPeer是在rtcloop中创建的,建议将PTZ协程放到同一个事件循环中运行,避免跨线程操作 - SQL注入防护:始终用参数化查询替代字符串格式化拼接SQL语句
- 错误处理:建议给协程添加
try/except捕获发送失败、数据库查询失败等异常,避免协程崩溃导致事件循环终止
内容的提问来源于stack exchange,提问作者1enn0k
相关产品推荐
相关产品推荐

