本文是.NET異步和多執行緒系列的第六章,本章主要對之前介紹過的async/await做一些補充說明,
下面我們直接來看下代碼和運行結果:
using System; using System.Threading; using System.Threading.Tasks; namespace MyAsyncAwait { /// <summary> /// await/async 是C#保留關鍵字,通常是成對出現,語法糖, /// /// 主執行緒呼叫async/await方法,主執行緒遇到await回傳執行后續動作, /// await后面的代碼會等著Task任務的完成后再繼續執行 /// 其實就像把await后面的代碼包裝成一個ContinueWith的回呼動作 /// 然后這個回呼動作可能是Task執行緒,也可能是新的子執行緒,也可能是主執行緒 /// /// 一個async方法,如果沒有回傳值,可以方法宣告回傳Task /// await/async能夠用同步的方式撰寫代碼,但又是非阻塞的, /// /// async方法在編譯后會生成一個狀態機(實作了IAsyncStateMachine介面) /// </summary> class Program { static void Main(string[] args) { Console.WriteLine($"當前主執行緒開始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); AwaitAsyncClass.TestShow(); Console.WriteLine($"當前主執行緒結束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Console.ReadKey(); } } /// <summary> /// await/async關鍵字 語法糖 /// await/async 要么不用 要么用到底 /// </summary> public class AwaitAsyncClass { public static void TestShow() { Test(); } private async static Task Test() { Console.WriteLine($"Test開始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Task<long> t = SumAsync(); Console.WriteLine($"遇到await主執行緒回來干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); { long lResult = await t; //await后面的代碼會由執行緒池的執行緒執行,非阻塞, Console.WriteLine($"最終得到的lResult={lResult}"); } { //t.Wait(); //主執行緒等待Task的完成,阻塞的 //long lResult = t.Result; //訪問Result,主執行緒等待Task的完成,阻塞的,效果跟t.Wait()一樣 //Console.WriteLine($"最終得到的lResult={lResult}"); } Console.WriteLine($"Test結束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); } /// <summary> /// 帶回傳值的Task /// 要使用回傳值就一定要等子執行緒計算完畢 /// </summary> private static async Task<long> SumAsync() { Console.WriteLine($"SumAsync start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); long result = 0; //await后面的代碼會等著Task任務的完成后再繼續執行 //其實就像把await后面的代碼包裝成一個ContinueWith的回呼動作 //然后這個回呼動作可能是Task執行緒,也可能是新的子執行緒,也可能是主執行緒 await Task.Run(() => { for (int k = 0; k < 2; k++) { Console.WriteLine($"SumAsync 第1個 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); } for (long i = 0; i < 999_999_999; i++) { result += i; } }); Console.WriteLine($"SumAsync 第1個 await Task.Run的后續任務開始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); await Task.Run(() => { for (int k = 0; k < 2; k++) { Console.WriteLine($"SumAsync 第2個 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); } for (long i = 0; i < 999_999_999; i++) { result += i; } }); Console.WriteLine($"SumAsync 第2個 await Task.Run的后續任務開始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); await Task.Run(() => { for (int k = 0; k < 2; k++) { Console.WriteLine($"SumAsync 第3個 await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); } for (long i = 0; i < 999_999_999; i++) { result += i; } }); Console.WriteLine($"SumAsync end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); return result; } } }
運行結果如下:

仔細觀察結果會發現:
主執行緒呼叫async/await方法,主執行緒遇到await后會回傳執行后續動作;
await后面的代碼會等著Task任務的完成后再繼續執行,其實就像把await后面的代碼包裝成一個ContinueWith的回呼動作;
然后這個回呼動作可能是Task執行緒,也可能是新的子執行緒,也可能是主執行緒;
await/async能夠用同步的方式撰寫代碼,但又是非阻塞的,
下面我們調整下Test方法后再運行(紅色的為調整部分):
private async static Task Test() { Console.WriteLine($"Test開始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Task<long> t = SumAsync(); Console.WriteLine($"遇到await主執行緒回來干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); { //long lResult = await t; //await后面的代碼會由執行緒池的執行緒執行,非阻塞, //Console.WriteLine($"最終得到的lResult={lResult}"); } { //t.Wait(); //主執行緒等待Task的完成,阻塞的 long lResult = t.Result; //訪問Result,主執行緒等待Task的完成,阻塞的,效果跟t.Wait()一樣 Console.WriteLine($"最終得到的lResult={lResult}"); } Console.WriteLine($"Test結束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); }
調整后運行結果如下:

仔細觀察結果會發現:
訪問Result,主執行緒會等待Task的完成,阻塞的,
其實async方法在編譯后會生成一個狀態機(實作了IAsyncStateMachine介面),有興趣的可以自行去了解下,
至此本文就介紹完了,有興趣的還可以看下我之前寫過一篇也是關于async/await的文章:https://www.cnblogs.com/xyh9039/p/11391507.html
Demo原始碼:
鏈接:https://pan.baidu.com/s/1jnG5IpteuKCdmF6-tr--cA 提取碼:3onm
此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/13622122.html
著作權宣告:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/1614.html
標籤:ASP.NET
