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

向运行中的asyncio循环添加摄像头协程导致其他任务停止运行

问题原因

你的runCamera虽然标记为async函数,但里面的OpenCV操作(vid.read()、cv.imshow()、cv.waitKey())全是阻塞式的同步调用,没有任何await异步逻辑。asyncio的事件循环是单线程运行的,一旦执行到runCamera里的阻塞循环,整个事件循环就被卡住了,根本没法切换到greet_every_two_seconds协程执行,所以问候循环直接停摆。

解决方案

针对这种阻塞操作和异步协程共存的场景,有两种实用的解决方式:

方式1:用asyncio线程执行器包装阻塞逻辑

把摄像头的阻塞循环放到线程里运行,让asyncio事件循环可以继续调度其他协程:

import asyncio
import cv2 as cv
from concurrent.futures import ThreadPoolExecutor

async def greet_every_two_seconds():
    while True:
        print('Hello World')
        await asyncio.sleep(1)

def camera_loop():
    vid = cv.VideoCapture(0)
    while True:
        ret, frame = vid.read()
        cv.imshow('frame', frame)
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
    vid.release()
    cv.destroyAllWindows()

async def runCamera():
    loop = asyncio.get_running_loop()
    with ThreadPoolExecutor() as executor:
        await loop.run_in_executor(executor, camera_loop)

def main():
    loop = asyncio.get_event_loop()
    asyncio.ensure_future(greet_every_two_seconds())
    asyncio.ensure_future(runCamera())
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        loop.close()

if __name__ == "__main__":
    main()

方式2:直接启动独立线程处理摄像头

如果不想依赖asyncio的线程执行器,也可以直接开一个线程单独跑摄像头逻辑,和asyncio事件循环并行:

import asyncio
import cv2 as cv
import threading

async def greet_every_two_seconds():
    while True:
        print('Hello World')
        await asyncio.sleep(1)

def camera_thread():
    vid = cv.VideoCapture(0)
    while True:
        ret, frame = vid.read()
        cv.imshow('frame', frame)
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
    vid.release()
    cv.destroyAllWindows()

def main():
    cam_thread = threading.Thread(target=camera_thread)
    cam_thread.daemon = True
    cam_thread.start()
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(greet_every_two_seconds())

if __name__ == "__main__":
    main()
场景适配说明

对于包含OpenCV摄像头这种阻塞式IO/UI操作的场景,用线程配合asyncio或者直接多线程都是合理选择。asyncio本身更擅长处理网络请求这类原生异步的任务,而对于底层是阻塞实现的操作,放到单独线程里是最直接的破局方式。

内容的提问来源于stack exchange,提问作者ill

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:50:23