为何使用await运算符时异步方法仍同步执行?
问题原因分析
- async方法在遇到第一个未完成的await之前,所有代码都是同步在调用线程上执行的:你当前代码里
DoAsync的a部分for循环、输出"I'm here B",甚至ReturnsString里输出"I'm here D"的逻辑,都在第一个await(也就是await Task.Delay(2000))之前,所以全部会同步阻塞执行,不会提前释放线程,自然就出现了全同步执行的效果。 - 调用
DoAsync的方式不符合异步规范:Main方法里直接写Console.WriteLine(exe3.DoAsync())没有等待任务完成,只会输出Task对象本身的类型信息,不会等后续异步逻辑执行完毕。
符合预期的修改方案
如果你想让a部分的逻辑和ReturnsString的异步逻辑并行执行,只需要调整代码顺序,先启动异步任务,再执行a部分逻辑,最后等待任务完成即可,修改后代码如下:
public class AsyncAwaitExe3 { public async Task<string> DoAsync() { string toReturn = ""; Console.WriteLine("I'm here A"); // 先启动异步任务,不立刻await,此时任务会在后台开始执行 var returnsTask = ReturnsString(); //a 此时执行for循环的同时,ReturnsString里的Task.Delay也在并行运行 for (int i = 0; i < 30; i++) { Console.WriteLine($"inside for {i}"); // 如果要模拟非阻塞等待可以换成await Task.Delay(1000),对应将循环也放在异步上下文即可 Thread.Sleep(1000); } //b Console.WriteLine("I'm here B"); // 此时再等待异步任务完成 toReturn = await returnsTask; //c Console.WriteLine("I'm here C"); return toReturn; } public async Task<string> ReturnsString() { Console.WriteLine("I'm here D"); await Task.Delay(2000); Console.WriteLine("I'm here E"); return "sharp sword"; } } static void Main(string[] args) { AsyncAwaitExe3 exe3 = new AsyncAwaitExe3(); // 等待异步任务执行完成后再输出结果,兼容所有.NET版本 var result = exe3.DoAsync().GetAwaiter().GetResult(); Console.WriteLine(result); Console.ReadKey(); }
如果你的项目是.NET Core 3.0+或者.NET 5+,可以直接把Main方法声明为async Task Main,直接用await等待DoAsync即可,写法更简洁。
内容的提问来源于stack exchange,提问作者Elaine Bel
相关产品推荐
相关产品推荐

