为何用create_task+asyncio.run从同步函数启动的异步协程未执行完毕?
问题原因
你的代码里asyncio.run(background_task())执行完后,事件循环直接被关闭了,这是核心问题:
asyncio.run()的逻辑是:创建事件循环 → 运行传入的协程 → 等待该协程完全结束后立即关闭事件循环background_task()里用asyncio.create_task(task())创建了后台任务,但它自己执行到print("b")就结束了,asyncio.run()随之关闭事件循环task()执行到第一个await asyncio.sleep(1)时会让出控制权,这时候事件循环已经被关闭,所以后续的迭代代码根本没机会运行,只能输出第一次迭代的内容
解决方案
因为你是在大型同步应用里启动后台异步任务,核心需求是让异步任务和同步代码并行运行,所以需要把事件循环放到独立线程中持续运行,避免被asyncio.run()的关闭逻辑打断。
修改后的代码示例:
import asyncio from time import sleep import sys import threading async def task(): for i in range(5): print(f"Background task iteration {i}") await asyncio.sleep(1) print('finished') async def background_task(): print("a") asyncio.create_task(task()) print("b") def main(): print("Main program started python", sys.version) # 创建事件循环并在后台线程启动 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) # 用守护线程运行事件循环,主线程结束时自动退出 threading.Thread(target=loop.run_forever, daemon=True).start() # 跨线程提交后台任务到事件循环 asyncio.run_coroutine_threadsafe(background_task(), loop) # 同步业务逻辑 for i in range(3): sleep(3) print(f"Main program iteration {i}") # 可选:如果同步代码结束后不需要异步任务继续运行,关闭事件循环 loop.call_soon_threadsafe(loop.stop) if __name__ == "__main__": main()
关键说明
- 把事件循环放到后台线程用
loop.run_forever()持续运行,不会被同步代码阻塞 - 跨线程提交协程必须用
asyncio.run_coroutine_threadsafe(),不能直接用asyncio.create_task()(后者只能在事件循环所在线程调用) - 守护线程(
daemon=True)会在主线程结束时自动终止,避免程序无法退出
内容的提问来源于stack exchange,提问作者Mehdi Ben Hamida
相关产品推荐
相关产品推荐

