程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> .NET異步編程初識async與await,asyncawait

.NET異步編程初識async與await,asyncawait

編輯:C#入門知識

.NET異步編程初識async與await,asyncawait


這是兩個關鍵字,用於異步編程。我們傳統的異步編程方式一般是Thread、ThreadPool、BeginXXX、EndXXX等等。把調用、回調分開來,代碼的邏輯是有跳躍的,於是會導致思路不是很清晰的問題,在.NET 4.5中,新推出的async、await關鍵字,可以幫助我們像寫同步方法一樣去寫異步方法(保證代碼的整齊清晰)。

  先來看個傳統同步方法例子:  

復制代碼
 1         static void Main(string[] args)
 2         {
 3             // 同步方式
 4             Console.WriteLine("同步方式測試開始!");
 5             SyncMethod(0);
 6             Console.WriteLine("同步方式結束!");
 7             Console.ReadKey();
 8         }
 9 
10         // 同步操作
11         private static void SyncMethod(int input)
12         {
13             Console.WriteLine("進入同步操作!");
14             var result = SyancWork(input);
15             Console.WriteLine("最終結果{0}", result);
16             Console.WriteLine("退出同步操作!");
17         }
18 
19         // 模擬耗時操作(同步方法)
20         private static int SyancWork(int val)
21         {
22             for (int i = 0; i < 5; ++i)
23             {
24                 Console.WriteLine("耗時操作{0}", i);
25                 Thread.Sleep(100);
26                 val++;
27             }
28             return val;
29         }
復制代碼

  可以從右圖中看到執行結果,是非常典型的同步執行方法。

  async關鍵字能用在方法、lambda表達式的聲明部分,用來標示此方法可能包含await關鍵字,只有擁有async才能在其內部使用await關鍵字。異步方法可以具有Task、Task<>或void的返回類型;await關鍵字則是用於返回值是“可等待”類型(awaitable)的方法或lambda表達式內,“awaitable”可以是任何類型(常見的有Task、Task<>),它必須公開一個GetAwaiter() 方法並且返回有效的”awaiter”。更詳細的信息可以參考“關於Async與Await的FAQ”,裡面介紹了這些概念與注意事項。

  當一個async方法,且內部包含await關鍵字,它就會在編譯的時候成為一個異步方法,如果沒有await關鍵字,則它將只會被當成一個同步方法來執行。如果對其內部實現感興趣可以參考“異步性能:了解 Async 和 Await 的成本”一文,相信對深入了解這種機制還是有所幫助的。

  現在我們嘗試使用新出的異步關鍵字async、await來改造成異步調用:

復制代碼        static void Main(string[] args)
        {
            // 異步方式
            Console.WriteLine("\n異步方式測試開始!");
            AsyncMethod(0);
            Console.WriteLine("異步方式結束!");
            Console.ReadKey(); 
        }  

        // 異步操作
        private static async void AsyncMethod(int input)
        {
            Console.WriteLine("進入異步操作!");
            var result = await AsyncWork(input);
            Console.WriteLine("最終結果{0}", result);
            Console.WriteLine("退出異步操作!");
        }

        // 模擬耗時操作(異步方法)
        private static async Task<int> AsyncWork(int val)
        {
            for (int i = 0; i < 5; ++i)
            {
                Console.WriteLine("耗時操作{0}", i);
                await Task.Delay(100);
                val++;
            }
            return val;
        }
復制代碼

   先來看結果吧,我們發現耗時操作已經是異步進行了。整體流程大概是先由Main函數異步調用AsyncMethod,並不等待AsyncMethod完成,繼續往下執行。而AsyncMethod方式在被調用後,在分配到時間片時開始啟動,執行函數體內容,並由於await AsyncWork語句而繼續異步調用AsyncWork,但由於await關鍵字,將在此等待AsyncWork完成後,再繼續往下執行。那麼,AyncWork也一樣的,被調用後,在分配到時間片時開始啟動,執行耗時操作。

  可以看到,使用了新的關鍵字後,同步與異步編程的語法差別進一步減少。隨著.NET 4.5的推出,許多新類庫和既有類庫都支持這種新型的異步語法(比如HttpClient、HttpServer、MemoryStream...),它們以類似ReadAsync、WriteAsync、SendAsync等分開方法來提供具有async聲明,且返回類型為Task、Task<>的異步工作方式。

  補充:

  剛才有朋友提到await Task.Delay(100)這條語句,這是為了讓AsyncWork成為異步方法才加的,如果你要進行的操作不支持await修飾怎麼辦,其實很簡單,使用Task.Factory.StartNew()就行了,舉例:

復制代碼
 1         // 異步操作
 2         private static async void AsyncMethod(int input)
 3         {
 4             Console.WriteLine("進入異步操作!");
 5             var result = await Task.Factory.StartNew((Func<object, int>)SyncWork2, input);
 6             Console.WriteLine("最終結果{0}", result);
 7             Console.WriteLine("退出異步操作!");
 8         }
 9 
10         // 模擬耗時操作(同步方法)
11         private static int SyncWork2(object input)
12         {
13             int val = (int)input;
14             for (int i = 0; i < 5; ++i)
15             {
16                 Console.WriteLine("耗時操作{0}", i);
17                 Thread.Sleep(100);
18                 val++;
19             }
20             return val;
21         }
復制代碼

  這樣,我們的SyncWork2實際上卻是異步執行的,所得結果與前面的異步方法一致,只是這樣一來輸入參數只能是object類型,需要進行類型轉化。另外,除了StartNew,我們還可以新建一個Task,然後調用Run,以完成同樣效果。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved