異步async與await的簡單探究
在學習.net core的過程中,到處見到異步的使用,Task、async、await隨處可見。有點疑惑,就去了解了下這個過程是怎樣的。
下面是一段代碼,去看看是怎麽執行的吧。
一、看看異步執行的方式
static void Main(string[] args) { Console.WriteLine("我是主線程:我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(); TestAsync(); Console.WriteLine("不等異步完成我先執行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
/// <summary> /// 異步方法 /// </summary> /// <returns></returns> static async Task TestAsync() { Console.WriteLine("我是TestAsync,調用我的線程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync中開啟的線程,ID是:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("TestAsync開啟的線程執行完後,此時的線程ID為:" + Thread.CurrentThread.ManagedThreadId); }
我們看到,主線程ID是1,然後調用TestAsync方法,註意在Main方法中,調用TestAsync我們沒有使用await,因為在Main方法中不支持async。
主線程調用TestAsync方法,進到TestAsync之後,打印出調用TestAsync方法的線程的ID。然後遇到Task.Run開啟新的線程,ID為3。Task.Run之前有await,
註意:await會阻塞當前線程,就是ID為3的線程,並且釋放調用TestAsync方法的線程,也即是主線程(ID為1),這個時候我們看到"不等異步完成我先執行了哈,我的ID是:1
輸出在"TestAsync開啟的線程執行完後,此時的線程ID為:4"之前。這就說明了,TestAsync方法中await釋放了主線程,同時Task.Run開啟了一個新的線程。
Task.Run開啟的線程是從線程池中取出的空閑線程。我運行幾次,發現最後一個輸出的結果不一樣。如下圖:
這應該說明,Task.Run開啟線程後,await後的代碼,是會重新開啟一個線程去執行的。
二、看看await是怎麽阻塞之後的代碼的。
static void Main(string[] args) { Console.WriteLine("我是主線程:我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(); TestAsync(); Console.WriteLine("不等異步完成我先執行了哈,我的ID是:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
/// <summary> /// 異步方法 /// </summary> /// <returns></returns> static async Task TestAsync() { Console.WriteLine("我是TestAsync,調用我的線程ID是:" + Thread.CurrentThread.ManagedThreadId); await TestAsync2(); Console.WriteLine("我被阻塞了,在TestAsync2執行之後才會執行,現在的線程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync中開啟的線程,ID是:" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("TestAsync開啟的線程執行完後,此時的線程ID為:" + Thread.CurrentThread.ManagedThreadId); }
static async Task TestAsync2() { Console.WriteLine(); Console.WriteLine("我是TestAsync2,調用我的線程ID是:" + Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("我是在TestAsync2中開啟的線程,ID是:" + Thread.CurrentThread.ManagedThreadId); int num = 0; for (int i = 0; i < 1000000; i++) { num += 1; } Console.WriteLine($"在TestAsync2中執行一個耗點兒時間的操作,num的值是{num}"); }); }
我們看到在TestAsync中調用TestAsync2前面加了await,"我被阻塞了,在TestAsync2執行之後才會執行,現在的線程ID是:3"
在TestAsync2方法執行之後,才輸出。並且這個時候主線程被釋放掉了,去輸出"不等異步完成我先執行了哈,我的ID是:1"。
好了,暫時就理解了這麽多,肯定有不對的地方,歡迎大家指正,時間不早了,早點休息,做個佛系養生的程序員,
異步async與await的簡單探究