0

我有一个异步协程,我想使用计时器/线程终止。协程基于来自 aiortc的这个示例。

args = parse_args()
client = Client(connection, media, args.role)

# run event loop
loop = asyncio.get_event_loop()

try:
    timer = None
    if args.timeout:
        print("Timer started")
        timer = threading.Timer(args.timeout, loop.run_until_complete, args=(client.close(),))
        timer.start()

    loop.run_until_complete(client.run())

    if timer:
        timer.join()
except KeyboardInterrupt:
    pass
finally:
    # cleanup
    loop.run_until_complete(client.close())

这不起作用并引发RuntimeError('This event loop is already running')

为什么这会引发错误?我的猜测是这是因为循环在不同的线程上运行。但是,创建一个新循环不起作用,因为它会将未来附加到另一个循环。

def timer_callback():
    new_loop = asyncio.new_event_loop()
    new_loop.run_until_complete(client.close())

之后,如何使用计时器来结束脚本?

4

2 回答 2

1

之后,如何使用计时器来结束脚本?

您可以调用asyncio.run_coroutine_threadsafe()以将协程提交到在另一个线程中运行的事件循环:

    if args.timeout:
        print("Timer started")
        timer = threading.Timer(
            args.timeout,
            asyncio.run_coroutine_threadsafe,
            args=(client.close(), loop),
        )
        timer.start()

但是请注意,由于您使用的是 asyncio,因此您不需要为计时器使用专用线程,您可以创建一个协程并告诉它在执行某项操作之前等待:

    if args.timeout:
        print("Timer started")
        async def close_after_timeout(): 
            await asyncio.sleep(args.timeout)
            await client.close()
        loop.create_task(close_after_timeout())
于 2022-01-12T09:33:06.703 回答
0

这不是我正在寻找的通用解决方案,我timeout向客户端构造函数添加了一个变量,并在其中client.run()添加asyncio.sleep(timeout)了退出循环的变量。这对我的目的来说已经足够了。

于 2022-01-12T00:48:25.887 回答