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

C#中await执行顺序不符预期?两种异步调用耗时差异咨询

C# 异步await调用耗时差异底层原理

很多刚接触C#异步的开发者会有一个认知误区:以为await操作才会触发异步任务启动。实际上C#中所有async方法返回的都是已启动的热任务(Hot Task):调用async方法的瞬间,方法就会同步执行到内部第一个await的未完成异步操作处,才会返回Task实例给调用方,后续逻辑在异步操作完成后通过回调执行,await的作用仅仅是等待任务完成、获取返回结果,本身不会触发任务启动。

逐行await写法总耗时6秒的原因

对应代码如下:

int a = await Task1();
int b = await Task2();
int c = await Task3();

return a+b+c;

这段代码是纯串行执行逻辑,流程如下:

  • 执行到第一行时才会调用Task1()启动任务,碰到内部的Task.Delay(1000)后,当前执行流就在此处挂起等待,整整1秒后Task1执行完毕返回10,才会进入下一行代码。
  • Task1完全结束后才会调用Task2()启动第二个任务,再等待2秒拿到返回值10,此时距离程序启动已经过去了1+2=3秒。
  • Task2完全结束后才会调用Task3()启动第三个任务,再等待3秒拿到返回值10,总耗时就是三个任务的等待时长累加:1+2+3=6秒。

这种写法下三个任务完全没有并发,和同步顺序调用的耗时没有区别。

先获取Task实例再await总耗时3秒的原因

对应代码如下:

var a = Task1();
var b = Task2();
var c = Task3();

return await a + await b + await c;

这段代码是并发执行逻辑,流程如下:

  • 第一行调用Task1()的瞬间,第一个任务就启动了,碰到内部的Task.Delay(1000)后立刻返回Task实例赋值给a,执行流不会等待,直接进入下一行。
  • 第二行调用Task2()的瞬间,第二个任务同步启动,碰到内部的Task.Delay(2000)后返回Task实例赋值给b,执行流继续往下走。
  • 第三行调用Task3()的瞬间,第三个任务同步启动,碰到内部的Task.Delay(3000)后返回Task实例赋值给c。
    这三行代码执行仅耗时几微秒,几乎可以忽略,此时三个延时任务已经处于同时运行的状态:Task1还需1秒完成,Task2还需2秒完成,Task3还需3秒完成。
  • 接下来执行await a等待第一个任务完成,1秒后拿到返回值10;此时Task2已经运行了1秒,还剩1秒等待时间,Task3已经运行了1秒,还剩2秒等待时间。
  • 接着执行await b等待第二个任务完成,仅需再等1秒就拿到返回值10;此时Task3已经运行了2秒,还剩1秒等待时间。
  • 最后执行await c等待第三个任务完成,再等1秒拿到返回值10。
    整个流程的总耗时取决于运行时间最长的Task3,也就是3秒,三个任务的等待时间是重叠的,属于并发执行。

内容的提问来源于stack exchange,提问作者murali krishnan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:36:25