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

异步函数中多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它的时候才启动。

具体到你的代码:

  1. 调用PrintAndWait("1")时,方法立即同步执行,直到遇到第一个await Task.Delay(1000)——此时Task.Delay会在后台启动一个定时任务,PrintAndWait返回一个未完成的Task,但后台的定时任务已经在运行了。
  2. 紧接着你调用PrintAndWait("2"),同样的逻辑,task2对应的异步流程也已经在后台启动,开始等待Delay完成。
  3. 当你执行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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:33:13