run_coroutine_threadsafe是否仅持有任务弱引用?需保存返回future吗?
asyncio.create_task与run_coroutine_threadsafe的引用问题解析
两者的强引用逻辑差异
asyncio.create_task:事件循环仅持有该任务的弱引用,必须由调用方保存返回的Task对象作为强引用。若未保存,当垃圾回收(GC)触发时,Task会被回收,协程会中途终止。你无法重现问题,大概率是因为协程执行速度快于GC触发时机,或者手动调用gc.collect()时任务已经执行完毕。asyncio.run_coroutine_threadsafe:该函数返回的concurrent.futures.Future对象,内部会在事件循环侧持有对应任务的强引用,直到任务完成。同时,事件循环的内部执行队列(如_ready队列)在任务待执行或执行过程中,也会持有任务的强引用,直到任务结束。这就是它的文档无需添加类似警告的原因。
关于无法重现create_task问题的说明
GC的触发时机是不确定的,即使手动调用gc.collect(),如果协程本身执行周期极短,在GC回收前任务已经完成,自然看不到中途终止的现象。可以尝试编写一个长时间运行的协程(比如用asyncio.sleep(10)模拟),不保存create_task返回的Task对象,然后在协程运行期间手动触发GC,就能复现任务被终止的情况。
结论
- 不保存
run_coroutine_threadsafe返回的Future不会导致协程无法运行,事件循环内部会持有强引用直至任务完成。 create_task的文档警告是必要的,因为它完全依赖调用方代码持有强引用才能保证任务执行完成。
内容的提问来源于stack exchange,提问作者alicederyn
相关产品推荐
相关产品推荐

