ASP.Net中的async+await非同步程式設計

跳躍的鍵盤手發表於2020-08-21

在.NET Framework4.5框架、C#5.0語法中,通過async和await兩個關鍵字,引入了一種新的基於任務的非同步程式設計模型(TAP)。在這種方式下,可以通過類似同步方式編寫非同步程式碼,極大簡化了非同步程式設計模型。

用法:

public async Task<int> GetDotNetCountAsync()
{
    // Suspends GetDotNetCount() to allow the caller (the web server)
    // to accept another request, rather than blocking on this one.
    var html = await _httpClient.GetStringAsync("https://dotnetfoundation.org");

    return Regex.Matches(html, @"\.NET").Count;
}

要點!!!

1.“async”用來標記一個方法為非同步方法,非同步方法體內需結合“await”關鍵字使用,如果沒有await,則該方法等同於一個普通方法。非同步方法命名規則通常以Async結尾。

2.“await”關鍵字只能在非同步方法中使用。

3.當在async非同步方法中遇到await操作時,await會阻塞該非同步方法不繼續往下執行,並將該非同步方掛起,將控制權轉到該非同步方法的呼叫者手中。

4.非同步方法的呼叫者獲得控制權之後:

   1)如果呼叫者需要使用非同步方法的返回結果,則繼續等待非同步方法執行完畢,再繼續往下執行。

   2)如果呼叫者不關心非同步方法的返回結果,則繼續往下執行。

 

場景一:async方法中未使用await

       static void Main(string[] args)
        {
            Console.WriteLine("執行前Main.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟①
            GetResultAsync();
            Console.WriteLine("執行結束Main....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟②
            Console.ReadKey();
        }

 
       async static Task<int> GetResultAsync()
        {
            Console.WriteLine("執行前GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟③
Task.Delay(
3000).Wait(); Console.WriteLine("執行結束GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟④ return 10; }

執行結果:步驟① ——>步驟③——>步驟④——> 步驟②

結果分析:

   我們會發現,主函式Main呼叫非同步方法GetResultAsync時,由於非同步方法缺少“await”關鍵字,主函式需等非同步方法步驟3,4全部執行結束後再繼續執行步驟2,執行順序完全和同步方法執行順序一致;

並且非同步方法會給出語法提示:缺少“await”關鍵字

 

場景2:非同步方法體內遇到await之後,立即將控制權轉到呼叫者手中

        static void Main(string[] args)
        {
            Console.WriteLine("執行前Main.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟①  
GetResultAsync(); Console.WriteLine(
"執行結束Main....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟② Console.ReadKey(); } async static Task<int> GetResultAsync() { Console.WriteLine("執行前GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟③ await Task.Delay(3000); Console.WriteLine("執行結束GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟④ return 10; }

執行結果:步驟① ——>步驟③——>步驟②——> 步驟④

結果分析:

   我們會發現,主函式Main呼叫非同步方法GetResultAsync,在遇到非同步方法中“await”關鍵字時

      1)阻塞了當前非同步方法並立即將控制權轉交給呼叫者主函式Main

      2)主函式獲得控制權後繼續執行方法體內步驟2,GetResultAsync方法則非同步執行(等待非同步操作結束之後執行步驟4)。

 

場景3:非同步方法體內遇到await之後,立即將控制權轉到呼叫者手中,呼叫者需等待非同步方法返回結果

        static void Main(string[] args)
        {
            Console.WriteLine("執行前Main.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟①
            Task<int> res = GetResultAsync();
            Console.WriteLine("執行結束Main....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟②
            Console.WriteLine("執行結果:" + res.Result + "....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟③
            Console.ReadKey();
        }
        async static Task<int> GetResultAsync()
        {
            Console.WriteLine("執行前GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟④
            await Task.Delay(3000);
            Console.WriteLine("執行結束GetResult.....執行緒ID:" + Thread.CurrentThread.ManagedThreadId.ToString());//步驟⑤
            return 10;
        }

執行結果:步驟① ——>步驟④——>步驟②——> 步驟⑤——> 步驟③

 結果分析:

   我們會發現,主函式Main呼叫非同步方法GetResultAsync,在遇到非同步方法中“await”關鍵字時

      1)阻塞了當前非同步方法並立即將控制權轉交給呼叫者主函式Main

      2)主函式獲得控制權後繼續執行方法體內步驟2和步驟3,GetResultAsync方法則非同步執行。

     3)當主函式執行步驟3時,由於步驟3需要列印非同步方法的返回結果,故需要等待非同步方法結束才能繼續。所以需先執行步驟5,然後再繼續執行步驟3。

 

最後,非同步程式設計的時候我們通常會結合Task來使用,感興趣的同學可以瞭解一下。厚積薄發!!!

相關文章