await直接调用异步函数与await已创建Task的执行差异
两种异步调用执行差异的底层核心原因
差异本质是异步任务的启动时机和await挂起当前执行流的时机是否分离,和Task本身的运行机制直接相关:
- 串行写法
Egg eggs = await FryEggsAsync(2);的执行逻辑
- 调用
FryEggsAsync(2)时,对应的异步任务会立刻启动 - 紧跟的
await会直接挂起当前方法的执行流程,直到该异步任务执行完成、返回结果后,才会继续执行后续代码 - 如果多个异步操作都采用这种「调用即await」的写法,下一个异步任务需要等上一个await结束才会被创建启动,自然是串行执行。
- 并行写法的执行逻辑
- 代码里先连续调用
FryEggsAsync、FryBaconAsync、ToastBreadAsync三个异步方法,赋值给对应的task变量:每调用一次异步方法,对应的后台任务就已经启动运行,且因为没有立刻加await,当前执行流不会被挂起,三个任务会同时在后台并行执行 - 后续的
await taskXxx只是等待对应任务执行完成、获取返回结果,不会阻塞其他已经启动的任务的运行。哪怕await的顺序是吐司先、再鸡蛋、再培根,也不会影响三个任务本身的并行状态,甚至如果鸡蛋比吐司先完成,等吐司的await结束后,拿鸡蛋结果的await会直接返回已经计算好的结果,不会额外等待。
额外补充你提到的WaitAll对比:Task.WaitAll是等所有传入的任务全部执行完成后,才会继续往下走后续逻辑;而这种「先启动所有任务再逐个await」的写法更灵活,某个任务先完成就能先处理该任务对应的后续逻辑(比如吐司先做好就先涂黄油果酱,不用等鸡蛋培根都熟)。
内容的提问来源于stack exchange,提问作者alekoo73
相关产品推荐
相关产品推荐

