You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

拆分AioRTC数据通道至多线程时遇协程未等待错误求助

问题解决:coroutine 'updatePTZReadOut' was never awaited 错误分析与修复

核心问题点

  1. 未正确await异步操作:asyncio.sleep(0.5)未加await,导致协程对象未被执行,触发警告
  2. 事件循环设置逻辑错误:asyncio.set_event_loop()返回None,导致后续loop变量无效
  3. 协程启动方式矛盾:用run_until_complete启动无限循环协程后,再调用run_forever完全多余
  4. 同步操作阻塞事件循环:数据库查询、readPTZCoords等同步代码会卡住async事件循环
  5. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 15:00:41