You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用asyncio创建任务为何总耗时10秒而非最长任务的4秒?

问题:asyncio异步任务总耗时不符合预期

我用asyncio编写了异步任务,预期总耗时为最长任务的4秒,但实际总耗时是10秒(0+1+2+3+4),请问原因是什么?

代码如下:

import asyncio,time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(f"what = {what}, at {time.strftime('%X')}")


background_tasks = set()

async def main():
    for i in range(5):
        task = asyncio.create_task(say_after(delay=i,what=i))
        
        # Add task to the set. This creates a strong reference.
        background_tasks.add(task)
        
        await task
        
        # To prevent keeping references to finished tasks forever,
        # make each task remove its own reference from the set after
        # completion:
        task.add_done_callback(background_tasks.discard) # discard is a set method.
        
if __name__=="__main__":
    asyncio.run(main())

执行结果:
执行结果

备注:我是参考Python官方文档编写的代码。


原因分析与解决办法

核心原因

循环中创建异步任务后立刻执行await task,会强制让main函数暂停,等待当前异步任务完全执行完毕才进入下一次循环。原本的异步并行逻辑被强行改成了串行执行,总耗时因此变成所有任务延迟时间的总和(0+1+2+3+4=10秒),而非并行时的最长延迟4秒。

官方文档用集合保存后台任务的示例,目的是让任务在后台并行运行,并非创建一个就等待一个。你错误地在循环内加入await task,破坏了异步并行的逻辑。

修正方案

把await task从循环内移出,等所有异步任务创建完成后,统一等待所有任务执行完毕。修改后的main函数如下:

async def main():
    for i in range(5):
        task = asyncio.create_task(say_after(delay=i,what=i))
        background_tasks.add(task)
        # 提前注册回调,避免任务完成后未清理内存引用
        task.add_done_callback(background_tasks.discard)
    
    # 等待所有后台任务执行完成
    await asyncio.gather(*background_tasks)

修改后所有任务会并行启动,总耗时约为4秒(最长任务的延迟时间),符合预期。

内容的提问来源于stack exchange,提问作者An old man in the sea.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:35:27