.NET4.5之初識async與await

來源:互聯網
上載者:User
本人是從.NET4.0剛出的時候接觸的.NET環境,所以學的東西就是4.0及其之前的。時代飛速前進,目測5.0也快出了吧,但一直也沒去接受新的技術。最近由於要學習Web API,快看完了,卻發現4.5已經大行其道了,於是又進行補腦。async與await便是其中之一:

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

static void Main(string[] args){    // 同步方式    Console.WriteLine("同步方式測試開始。");    SyncMethod(0);    Console.WriteLine("同步方式結束。");    Console.ReadKey();}// 同步操作private static void SyncMethod(int input){    Console.WriteLine("進入同步操作。");    var result = SyancWork(input);    Console.WriteLine("最終結果{0}", result);    Console.WriteLine("退出同步操作。");}// 類比耗時操作(同步方法)private static int SyancWork(int val){    for (int i = 0; i < 5; ++i)    {        Console.WriteLine("耗時操作{0}", i);        Thread.Sleep(100);        val++;    }    return val;}

  可以從右圖中看到執行結果,是非常典型的同步執行方法。
  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()就行了,舉例:
  

// 非同步作業private static async void AsyncMethod(int input){    Console.WriteLine("進入非同步作業。");    var result = await Task.Factory.StartNew((Func<object, int>)SyncWork2, input);    Console.WriteLine("最終結果{0}", result);    Console.WriteLine("退出非同步作業。");}// 類比耗時操作(同步方法)private static int SyncWork2(object input){    int val = (int)input;    for (int i = 0; i < 5; ++i)    {        Console.WriteLine("耗時操作{0}", i);        Thread.Sleep(100);        val++;    }    return val;}

  這樣,我們的SyncWork2實際上卻是非同步執行的,所得結果與前面的非同步方法呼叫一致,只是這樣一來輸入參數只能是object類型,需要進行類型轉化。另外,除了StartNew,我們還可以建立一個Task,然後調用Run,以完成同樣效果。
  目前來說,這種非同步工作還是會造成本人使用上的不適,不過如果在將來的版本中,繼續推廣使用,相信不久便能熟練,且加快寫代碼的速度,編寫出邏輯清晰的代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.