为何直接await异步方法同步执行,先声明Task变量则异步执行?
异步任务调用方式的差异解析
我正试图理解异步任务的正确调用方式,请看以下代码:
var stopWatch = new Stopwatch(); // TEST 1 AWAITS THE ASYNC TASKS DIRECTLY stopWatch.Start(); Console.WriteLine($"Test 1 Begin: {stopWatch.ElapsedMilliseconds}"); await Task1(stopWatch); await Task2(stopWatch); Console.WriteLine($"Test 1 End: {stopWatch.ElapsedMilliseconds}"); Console.WriteLine(); Console.WriteLine(); stopWatch.Restart(); // TEST 2 CREATES A LOCAL VARIABLE OF THE TASK THEN AWAITS THE LOCAL VARIABLE Console.WriteLine($"Test 2 Begin: {stopWatch.ElapsedMilliseconds}"); var task1 = Task1(stopWatch); var task2 = Task2(stopWatch); await task1; await task2; Console.WriteLine($"Test 2 End: {stopWatch.ElapsedMilliseconds}"); async Task Task1(Stopwatch stopWatch) { Console.WriteLine($"Task 1 Start: {stopWatch.ElapsedMilliseconds}"); await Task.Delay(2000); Console.WriteLine($"Task 1 End: {stopWatch.ElapsedMilliseconds}"); } async Task Task2(Stopwatch stopWatch) { Console.WriteLine($"Task 2 Start: {stopWatch.ElapsedMilliseconds}"); await Task.Delay(2000); Console.WriteLine($"Task 2 End: {stopWatch.ElapsedMilliseconds}"); }
测试1总耗时:4秒
测试2总耗时:2秒
为何测试1会同步执行,而测试2是异步执行?
核心差异:任务的启动与等待时机
测试1:串行执行
执行await Task1(stopWatch)时,程序先同步运行Task1的代码,直到遇到await Task.Delay(2000)——此时Task1挂起并返回未完成的任务,主线程开始等待该任务结束(耗时2秒)。只有等Task1完全执行完毕,才会调用Task2(stopWatch),重复相同的等待流程。两个任务是依次启动、依次完成的,总耗时为2秒+2秒=4秒。测试2:并行执行
先执行var task1 = Task1(stopWatch),Task1启动后运行到await处挂起,返回未完成的任务;紧接着立刻执行var task2 = Task2(stopWatch),Task2也同步启动并挂起。此时两个任务已同时在后台执行,后续的await task1和await task2只是等待这两个已启动的任务完成。因为任务并行运行,总耗时接近2秒(忽略启动的微小时间差)。
简单总结:测试1是"做完一个再启动下一个",测试2是"先启动所有任务,再一起等结果",这就是两者耗时差异的根本原因。
内容的提问来源于stack exchange,提问作者wamaral
相关产品推荐
相关产品推荐

