1. 程式人生 > >異步async與await的簡單探究

異步async與await的簡單探究

輸出 程序 ima c中 調用 mage 開啟 同時 休息

  在學習.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的簡單探究