我不确定这里发生了什么。据我所知,一旦方法遇到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?
答案 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;
}