轉 .NET4.5之初識async與await

來自:http://www.cnblogs.com/lekko/archive/2013/03/05/2944282.html  html

 

 本人是從.NET4.0剛出的時候接觸的.NET環境,因此學的東西就是4.0及其以前的。時代飛速前進,目測5.0也快出了吧,但一直也沒去接受新的技術。最近因爲要學習Web API,快看完了,卻發現4.5已經大行其道了,因而又進行補腦。async與await即是其中之一:編程

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

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

 

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 的成本」一文,相信對深刻了解這種機制仍是有所幫助的。post

  如今咱們嘗試使用新出的異步關鍵字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,以完成一樣效果。

  目前來講,這種異步工做仍是會形成本人使用上的不適,不過若是在未來的版本中,繼續推廣使用,相信不久便能熟練,且加快寫代碼的速度,編寫出邏輯清晰的代碼。

相關文章
相關標籤/搜索