没有await的嵌套异步方法块
本文关键字:异步方法 嵌套 await 没有 | 更新日期: 2023-09-27 18:17:12
我不确定这里发生了什么。据我所知,只要方法遇到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;
}
在main中,我调用
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?
使用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;
}