網上關於async/await的知識有很多,看了很多但不如自己實踐一遍來得快,所以這里記錄下我的理解和大家學習下。
首先以最簡單的同步方法來開始如下
private static void Test() { Console.WriteLine(2); GetV(); Console.WriteLine(6); } private static void GetV() { Console.WriteLine(3); Console.WriteLine(4); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); Test(); Console.WriteLine(7); }
輸出如下
當時當我們簡單的使用Task.Run時
private static void Test() { Console.WriteLine(2); GetV(); Console.WriteLine(6); } private static void GetV() { Console.WriteLine(3); Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); Test(); Console.WriteLine(7); }
,因為分配了新的線程,所以4會最晚打印出來。
這時候我們使用async/await呢?
private static async Task Test() { Console.WriteLine(2); await GetV(); Console.WriteLine(6); } private static async Task GetV() { Console.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.WriteLine(5); } static void Main(string[] args) { Console.WriteLine(1); var v= Test(); Console.WriteLine(7); }
因為await會時被修飾的代碼處於等待狀態,就相當於阻塞那段代碼,Test方法里面執行到await時就會等待Getv的方法的執行,就會阻塞Test方法,但是不會阻塞Main方法,可以理解為await將阻塞的控制權交給了Test方法。所以這個時候打印結果為
但是當我們把Test的await去掉了,這時候Test方法就沒有了阻塞的權限,而是去尋找下一個await來轉移控制權,如下
private static void Test() { Console.Out.WriteLine(2); GetV(); Console.Out.WriteLine(6); } private static async Task GetV() { Console.Out.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.Out.WriteLine(5); } static void Main(string[] args) { Console.Out.WriteLine(1); Test(); Console.Out.WriteLine(7); string str = Console.ReadLine(); }
這個時候就不會阻塞Test方法,結果如下
如果在main方法里面使用Task.GetAwaiter或者Task.Result呢,這兩個東西我的理解就是阻塞線程,等待異步返回結果,但是它阻塞的是當前的方法,如下代碼
private static async Task Test() { Console.Out.WriteLine(2); GetV(); Console.Out.WriteLine(6); } private static async Task GetV() { Console.Out.WriteLine(3); await Task.Run(() => { Thread.Sleep(10000); Console.WriteLine(4); }); Console.Out.WriteLine(5); } static void Main(string[] args) { Console.Out.WriteLine(1); Test().GetAwaiter().GetResult() ; Console.Out.WriteLine(7); string str = Console.ReadLine(); }
它只會阻塞main方法的,但是對於Test方法它是無法阻塞的,Test方法仍然會異步執行,4,5仍然以異步的方法打印出來,所以打印結果如下
Task.Result也是如此,只會阻塞當前的方法,我覺得和await相似,只給了當前使用Task.GetAwaiter或者Task.Result的方法阻塞全,沒有權利阻塞別的方法。
打個廣告:游戲也能賺錢?如果你熱愛游戲,並且想通過游戲贏得零花錢,5173是個不錯的選擇