如果没有连接客户端,WebSocket将冻结程序

u1ehiz5o  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(148)

我正在创建一个实时事件检测器。它读取游戏流并检测一些事件,如目标、计时器更新等。所有事件都应该通过WebSocket发送,所以我使用了python websockets和asyncio库。代码如下:

main_stack = []

cap = cv2.VideoCapture("vid_2.mp4")
game = Game(main_stack)

async def handler(websocket):
    while True:
        ret, frame = cap.read()
        await asyncio.sleep(0.05)
        game.run_detectors(frame)
        while main_stack:
            elem = main_stack.pop()
            await websocket.send(elem.get_json())

async def main():
    async with websockets.serve(handler, "", 8765):
        await asyncio.Future()

if __name__ == "__main__":
    asyncio.run(main())

game.run_detectors(frame)行在检测到事件时将事件添加到主堆栈。然后如果堆栈中有一些事件,则通过WebSocket发送它们。问题是当没有连接客户端时,程序会冻结,从真实的运行的转换中丢失事件。我如何更改代码,因此堆栈的更新独立于WebSocket。websocket会不断检查更新并发送事件(如果它们存在于堆栈中)。

pkwftd7m

pkwftd7m1#

您应该在一个单独的thread中运行游戏,并将事件添加到queue中,然后弹出它们并将它们发送到WebSocket处理程序中。注意,这只适用于单个连接,如果您有多个连接,则需要编写某种逻辑来保存状态(已发送哪些事件等)。如果没有附加逻辑,则只有其中一个连接会收到事件,而不是所有连接。
下面是一个基本示例,它应该是什么样子。

from threading import Thread
from queue import Queue, Empty
import time

main_stack = Queue()

cap = cv2.VideoCapture("vid_2.mp4")
game = Game(main_stack) # Adapt logic in the Game class to put events in the queue

async def handler(websocket):
    while True:
        try:
            elem = main_stack.get(timeout=1e-3) # Try to fetch an event from queue with a 1 ms timeout in order to prevent high CPU usage
        except Empty:
            continue # In case the queue is empty, repeat fetching
        await websocket.send(elem.get_json())

async def main():
    async with websockets.serve(handler, "", 8765):
        await asyncio.Future()

def game_loop(game, cap):
    while True:
        ret, frame = cap.read()
        game.run_detectors(frame)
        time.sleep(0.05)

if __name__ == "__main__":
    game_thread = Thread(target=game_loop, args=(game, cap), daemon=True)
    game_thread.start()
    asyncio.run(main())

相关问题