嵌套的异步方法块没有等待

时间:2015-10-09 23:25:48

标签: c# .net asynchronous async-await

我不确定这里发生了什么。据我所知,一旦方法遇到await关键字,它就会有效地返回,然后在Task完成后继续执行。但是,这不是我观察到的行为。我有两个简单的方法:

public static async Task<bool> Level1()
{            
    var t = await Level2();      
    Console.WriteLine("L1 done.");  
    return t;                     
}

public static async Task<bool> Level2()
{
    int delay = 10;
    Thread.Sleep(100);
    var t = new TaskFactory();

    t.StartNew(() => { Thread.Sleep(delay); });
    Console.WriteLine("L2 done.");
    return true;
}

主要是我打电话

static void Main(string[] args)
{
    Level1();
    Console.WriteLine("Main done.");
}

现在,我希望Main()在调用Level1()之后继续执行,因为它没有等待,并且因为Level1()包含await关键字。但是,结果输出是

L2 done.
L1 done.
Main done.

表明我的异步方法正在同步运行。修改Level2()以使用await关键字可以解决问题,并且Level1()调用不再阻止。为什么我需要在嵌套方法Level2()方法中使用“await”来阻止Level1()阻止Main?

1 个答案:

答案 0 :(得分:4)

使用async关键字标记方法不会使其异步。它只允许使用await(并使用任务包装结果或异常)。

如果你的“async”方法没有等待其中的任何异步操作,那么该方法是完全同步的,并且将在调用线程上运行。

您可能遗漏的是,使用await并不一定会使方法异步运行,在未完成的任务上使用await也是如此。当任务已经完成时,没有理由暂停该方法。您可以从任务中获取结果并保持同步运行。

在您的情况下,Level2同步运行。当Level1准备等待其任务时,它已经完成,因此Level2保持同步运行。请记住,您等待任务,而不是方法,因此您的代码实际运行如下:

public static async Task<bool> Level1()
{            
    var $task = Level2(); // Runs synchronously
    var t = await $task; // Awaiting a completed task      
    Console.WriteLine("L1 done.");  
    return t;                     
}
相关问题