异步函数中多Task执行疑问:是否误解了await机制?
对await异步执行机制的误解解析
测试代码
class EvaluateAwait { static async Task Main() { Console.WriteLine("Main func: Thread ID = " + Thread.CurrentThread.ManagedThreadId); Task task1 = PrintAndWait("1"); Console.WriteLine("Task 1 created"); Task task2 = PrintAndWait("2"); Console.WriteLine("Task 2 Created"); await task1; await task2; Console.WriteLine("Main Returned."); } static async Task PrintAndWait(string id) { for (int i = 0; i < 50; i++) { await Task.Delay(1000); Console.WriteLine("Thread ID:"+ Thread.CurrentThread.ManagedThreadId + " | Task ID:" +id + " | " ); } Console.WriteLine("Thread ID: " + Thread.CurrentThread.ManagedThreadId + " | Task ID: " + id + "completed"); } }
预期执行流程
- Main函数打印自身线程ID
- Main进入
task1对应的PrintAndWait方法,遇到第一个await Task.Delay(1000)时,该方法返回未完成的Task - Main打印"Task 1 created"
- Main进入
task2对应的PrintAndWait方法,遇到第一个await Task.Delay(1000)时,该方法返回未完成的Task - 执行
await task1,认为Main会在此处暂停,需等task1完成后才执行后续代码,因此预期task1先完成50次打印,再轮到task2执行 - 执行
await task2,task2完成50次打印
实际输出
Main func: Thread ID = 1 Task 1 created Task 2 Created Thread ID:7 | Task ID:2 | Thread ID:10 | Task ID:1 | Thread ID:7 | Task ID:2 | Thread ID:10 | Task ID:1 |
问题解析
你确实对await的机制存在误解,核心点在于:异步Task在被创建(调用异步方法)时就已经开始执行了,而不是等到await它的时候才启动。
具体到你的代码:
- 调用
PrintAndWait("1")时,方法立即同步执行,直到遇到第一个await Task.Delay(1000)——此时Task.Delay会在后台启动一个定时任务,PrintAndWait返回一个未完成的Task,但后台的定时任务已经在运行了。 - 紧接着你调用
PrintAndWait("2"),同样的逻辑,task2对应的异步流程也已经在后台启动,开始等待Delay完成。 - 当你执行
await task1时,Main方法只是暂停自身的执行,等待task1完成,但此时task2已经在后台跑起来了,所以两个Task的后续打印会交替出现,呈现并行执行的状态。
如果想要让task1完全执行完再启动task2,你需要在创建task2之前就await task1,修改后的Main方法如下:
static async Task Main() { Console.WriteLine("Main func: Thread ID = " + Thread.CurrentThread.ManagedThreadId); // 先启动并等待task1完成 await PrintAndWait("1"); Console.WriteLine("Task 1 completed"); // 再启动并等待task2完成 await PrintAndWait("2"); Console.WriteLine("Task 2 completed"); Console.WriteLine("Main Returned."); }
这样就能实现你预期的串行执行效果。
内容的提问来源于stack exchange,提问作者Yiqun Cui
相关产品推荐
相关产品推荐

