使用asyncio.create_task创建的任务为何无法被垃圾回收?
为什么用asyncio.create_task()创建的任务没被垃圾回收?
以下是测试代码:
import asyncio import gc c = 0 async def run(): global c try: while True: await asyncio.sleep(1) c += 1 except Exception as e: print(e) async def main(): task = asyncio.create_task(run()) del task while True: await asyncio.sleep(0.2) print(c) gc.collect() asyncio.run(main())
预期结果:
0 0 0 asyncio.CancelledError
实际结果:
0 0 0 0 0 1 1 1 1 1 .. 101 101 101 101 101 102 ...
原因分析
问题出在asyncio.create_task()的运行机制上:当调用这个函数创建任务时,asyncio的事件循环会自动持有该任务的强引用,并将其加入待执行任务队列。哪怕你在main函数里删除了task变量,事件循环的引用依然存在,垃圾回收器无法回收这个任务,所以run()里的无限循环会持续执行,c也就不断累加。
说白了:你删的只是自己手里的任务引用,事件循环还攥着任务不放,任务自然不会停止。
实现预期结果的修改方法
如果想要任务被取消并触发CancelledError,需要主动调用任务的cancel()方法,而非单纯删除变量。修改后的main函数如下:
async def main(): task = asyncio.create_task(run()) task.cancel() # 主动取消任务 del task while True: await asyncio.sleep(0.2) print(c) gc.collect()
修改后,任务会被立即取消,run()里的异常会被捕获并打印,c会一直保持0,符合预期结果。
内容的提问来源于stack exchange,提问作者mq7
相关产品推荐
相关产品推荐

