你可以使用異步程式設計來避免你的應用程式的性能瓶頸并且加強總體的響應。然而,用傳統的技術來寫異步應用是複雜的,同時編寫,調試和維護都很困難。
VS2012介紹了簡單的方法,那就是異步程式設計,它在.Net Framework 4.5和Windows 運作時提供了異步支援。編譯器做了開發者以前做的困難的工作,而且你的應用保持了類似于異步代碼的邏輯結構。結果,你輕易地就獲得了所有異步程式設計的優勢。
異步對于可能阻塞的活動是至關重要的。例如當你的應用通路Web的時候,通路web資源有時有點慢或者延時,如果這樣一個活動在同步程序中阻塞了,整個應用就必須等待。在異步程序中,此應用可以繼續其他的工作,而不依賴于web資源直到這個可能阻塞的任務完成。
下表展示了異步程式設計提升響應的典型領域。陳列的來自Framework 4.5 和the Windows Runtime 的APIs包含了支援async程式設計的方法。
應用領域
包含異步方法的APIs
Web 通路
處理檔案
處理圖檔
WCF程式設計
<a href="http://go.microsoft.com/fwlink/p/?LinkID=192382">Synchronous and Asynchronous Operations</a>
對于通路UI線程的應用,異步被證明是特别有價值的,因為所有Ui相關的活動通常共享一個線程。如果同步應用的任何一個程序被阻塞了,那麼所有程序都被阻塞了。屆時你的應用停止了響應,你可能推斷它出錯了,然而它卻僅僅在等待。
當你使用異步方法的時候,應用會繼續響應UI。你可以調整或者最小化視窗,或者如果你不想等待應用完成,那就關了它。
基于異步的方法相當于在設計異步操作時,向可供你選擇的選項增加了自動的傳輸裝置。那就是說,你以更少的付出卻獲得了所有傳統異步程式設計的好處。
關鍵字async和await是異步程式設計的核心。通過使用這兩個關鍵字,可以使用.NET Framework 或者Windows Runtime的資源來建立異步方法,這就像建立同步方法一樣簡單。使用await和async定義的方法為異步方法。
下面是一個異步方法的例子。代碼中的所有你都應該看着很熟悉。


如果AccessTheWebAsync在調用GetStringAsync 和等待完成之間沒有其他要處理的代碼,可以用下面一條單句簡化代碼。
下面總結了一些上面的異步方法的例子的特點:
方法簽名包括async修飾符
異步方法的命名,按照慣例,以“Async”字尾結尾
傳回類型隻能是這三種:Task<TResult>,Task或void
方法通常至少包括一個await表達式,await标記了一個點,這個點就是直到異步操作完成後異步方法才繼續執行。同時,方法是延遲的,控制傳回到方法的調用者。
了解異步程式設計最重要的事情是 控制流如何從一個方法移動到另一個方法。下圖帶你了解這個過程。
對應數字序号的解釋如下:
事件句柄調用并等待AccessTheWebAsync 異步方法。
AccessTheWebAsync 建立一個HttpClient執行個體,并調用GetStringAsync異步方法來下載下傳website的内容,儲存到字元串。
GetStringAsync發生了一些事情,延遲了方法的進度。也許必須等待站點下載下傳或者一些其他的阻塞活動。為避免阻塞資源,GetStringAsync轉讓控制權給它的調用者AccessTheWebAsync 。
因為getStringTask還沒有被await,是以AccessTheWebAsync 可以不依賴GetStringAsync傳回的最終結果繼續工作。這項工作是一個同步方法DoIndependentWork。
DoIndependentWork是一個處理一些事情的同步方法,并且傳回給它的調用者。
AccessTheWebAsync 已經完成了它能做的事情,但getStringTask還沒有傳回結果。AccessTheWebAsync 下一步想要計算并傳回已經下載下傳的字元串的長度,但是該方法直到有字元串時才能計算那個值。
是以,AccessTheWebAsync 使用了一個await操作符來延遲它的進度,并且轉讓控制權給調用AccessTheWebAsync 的方法。AccessTheWebAsync 傳回一個Task<int>給調用者。這個task代表一種産生一個整數結果的允諾,這個整數結果就是下載下傳字元串的長度。
【注意:如果GetStringAsync(并且進而getStringTask)在AccessTheWebAsync等待它之前完成,那麼控制權保留在AccessTheWebAsync中。如果調用的異步過程(getStringTask)已經完成了,延遲和後來傳回到AccessTheWebAsync的代價将會被浪費,因而AccessTheWebAsync沒必要等待最終的結果了。】
在調用者内部(這個例子中的事件句柄),處理模式繼續執行。在等待異步傳回的結果之前,調用者可能處理其他的工作而不依賴來自AccessTheWebAsync的結果,或者調用者可能會立即等待。事件句柄等待AccessTheWebAsync,AccessTheWebAsync等待GetStringAsync。
GetStringAsync完成并産生了字元串結果。這個字元串結果可能沒有按你期望的那樣通過GetStringAsync的調用被傳回。(記住步驟3中該方法已經傳回了一個task。)相反,這個字元串被儲存到代表這個方法完成的任務對象getStringTask中。Await操作符檢索來自getStringTask的結果。指派語句将檢索的結果指派給urlContent變量。
當AccessTheWebAsync獲得字元串結果時,該方法可以計算這個字元串的長度。然後AccessTheWebAsync的工作也完成了,等待中的事件句柄可以恢複了。
你可能想知道在哪裡找到支援異步的像GetStringAsync的方法。.NET Framework 4.5包含了許多對async和await有效的成員。你可以通過“Async”字尾和Task或Task<TResult>的傳回類型來識别這些成員。比如,System.IO.Stream類中,在同步方法CopyTo, Read和 Write的旁邊包含了很多像CopyToAsync, ReadAsync和WriteAsync的方法。
async方法規定為非阻塞操作。當等待的task運作的時候,async方法的await表達式不會阻塞目前線程。相反,該表達式注冊目前方法的剩餘作為延續,并且傳回控制權給async方法的調用者。
async和await關鍵字不會造成額外的線程被建立。async方法不會要求多線程是因為async方法沒有運作在它自己的線程上。該方法運作在目前的同步上下文上,隻有該方法激活的時候才會在該線程上使用時間。你可以使用Task.Run()來将CPU受限的工作移動到背景線程中,但是背景線程不會幫助處理僅僅等待結果變成可利用的。
按照慣例,給方法添加async修飾符,給方法名追加“Async”字尾。
下面的代碼來自WPF應用的MainWindow.xaml.cs。
本文轉自tkbSimplest部落格園部落格,原文連結:http://www.cnblogs.com/farb/p/4841729.html,如需轉載請自行聯系原作者