異步編程系列第01章 Async異步編程簡介


2016.10.11補充 三個月過去了,回頭來看,我不得不承認這是一系列失敗的翻譯。過段時間,我將重新翻譯。

寫在前面

  在學異步,有位園友推薦了《async in C#5.0》,沒找到中文版,恰巧也想提高下英文,用我拙劣的英文翻譯一些重要的部分,純屬娛樂,簡單分享,保持學習,謹記謙虛。

  如果你覺得這件事兒沒意義翻譯的又差,盡情的踩吧。如果你覺得值得鼓勵,感謝留下你的贊,祝各位愛技術的園友在今后每一次應該猛烈突破的時候,不選擇知難而退。在每一次應該獨立思考的時候,不選擇隨波逐流,應該全力以赴的時候,不選擇盡力而為,不辜負每一秒存在的意義。

本文版權歸博客園和作者吳雙本人共同所有。   轉載和爬蟲請注明原文鏈接http://www.cnblogs.com/tdws/p/5617242.html,博客園 蝸牛 2016年6月26日。

目錄

第01章 異步編程介紹

第02章 為什么使用異步編程

第03章 手動編寫異步代碼

第04章 編寫Async方法

第05章 Await究竟做了什么

第06章 以Task為基礎的異步模式

第07章 異步代碼的一些工具

第08章 哪個線程在運行你的代碼

第09章 異步編程中的異常

第10章 並行使用異步編程

第11章 單元測試你的異步代碼

第12章 ASP.NET應用中的異步編程

第13章 WinRT應用中的異步編程

第14章 編譯器在底層為你的異步做了什么

第15章 異步代碼的性能

第1章 異步編程介紹
   讓我們從C#5.0異步編程Async和他將對你意味着什么來開始介紹吧!
 
異步編程

   如果我們在一個耗時的操作中使用異步的代碼,在其執行過程中,我們不需要無謂的等待。這種方式和在耗時操作的整個執行過程中的阻塞型代碼是相對的。

我們所說的耗時操作包括:

·網絡請求

·硬盤數據訪問

·延遲一段時間的操作

  全部的區別在於正在運行代碼的線程。在廣泛應用的編程語言當中,你的代碼運行在操作系統的線程中。如果在遇到耗時操作時,你的線程可以繼續去做其他事情,這就是異步編程。如果你的線程除了等待什么也不做,那就是同步的或者說是阻塞型代碼。

當然我們還有第三種方式去處理耗時操作—輪詢。這是一種不斷重復“詢問”耗時操作是否完成的操作。盡管它在處理段時間操作上有自己的地位,但這通常不是一個好的解決方案。

 

  你也許在過去的工作中使用過異步編程。你可能開啟一個新的線程或者使用線程池,這也是異步編程,因為你所工作的線程可以不被阻塞地去繼續做其他事情。而你的console app,像Console.ReadLine(),這就是阻塞型,在web app中,如果也是這樣的設計等待用戶輸入,將會是多么糟糕呀。

  異步編程中很常見的難點在於這個操作在什么時候結束,以便於執行下一步的某些操作。但是這在阻塞型代碼中,很容易做到:你只需要在將接下來的代碼寫在耗時操作的下一行就好。如果不加以處理,這種方式在異步的世界中是怎樣也行不通的。因為幾乎可以確定的是,你下一行代碼是在耗時操作完成之前就已經執行了。

  為了解決這個問題,我們發明了一些方式,為了在后台操作完成后去執行下一步操作:

·將下一步操作所需的代碼插在耗時操作代碼主體的后面

·注冊一個當耗時操作結束時會觸發的方法

·在完成后傳遞委托或者Lambad(回調)

  如果你下一個操作需要在特定的線程上執行(例如Winform和WPF的UI線程),你還需要在這個線程上安排隊列排序,這是很復雜的。

 
異步代碼有什么了不起的?

   異步編程釋放了它開始的線程,這有許多原因確實不錯。首先,線程占用並且占用很少的資源,通常只用一個線程就可以完成主要的工作,就像UI線程,但是如果你不盡快釋放它,你的app就會出現未響應狀態。我們將會討論更多的原因在下一章。

   最重要的,也是最令我激動的一點是:異步編程讓我們得以有機會去盡情享受計算機並行計算帶來的好處。異步編程讓我們以新的並且合理的方式構建應用程序,用更細粒度的並行和無需編寫難以維護的復雜代碼。第十章將會詳細探討此可能性。

 
什么是異步編程?

   在C#5.0當中,微軟編譯器團隊為我們增加了一個強大的新功能。

   它以兩個新型關鍵字出現:。

·async

·await

   它當然依賴於一些環境,要求你使用.NET FrameWork4.5,才能你的async代碼有用。

Async是屬於C#編譯器的一個功能,不能被封裝到一個類庫,它對你的源代碼進行改造,就像在早期C#版本對Lambda和迭代器所做的事情一樣。

 

   通過免去早期C#版本異步編程所需的復雜模式和代碼,這個新功能使異步變得非常簡單。有了這個功能,我們可以合理地用異步編程的風格編寫整個項目。

   異步編程一直在C#中是可行的的,它以前涉及編程者大量的手工工作,現在C#的async關鍵出現后,異步編程的使用變得非常容易。

 
異步編程Async做了什么?

   Async功能提供了一種讓你表達在耗時操作后需要做什么事情(執行什么代碼)的方式,並且它易讀易懂,表現為異步編程。

   Async方法被編譯器轉化的像你平時所寫的阻塞代碼,這里有一段簡單的下載網頁的阻塞型代碼:

private void DumpWebPage(string uri)
{
WebClient webClient = new WebClient();
string page = webClient.DownloadString(uri);
Console.WriteLine(page);
}

   這里還有一段使用Async實現相同功能的代碼:

private asyncvoid DumpWebPageAsync(string uri)
{
WebClient webClient = new WebClient();
string page = awaitwebClient.DownloadStringTaskAsync(uri);
Console.WriteLine(page);
}

   兩段代碼在表面上看起來是非常相似的,但是在其外表下,有很大的不同。

   被標記為Async的方法,要求方法使用await關鍵字,為了遵循慣例,我們也再方法的后綴名加上了Async。

   有趣的地方是await關鍵字,當編譯器遇到它時,他將方法分開(chop the method up),事實上它是很復雜的,所以現在我介紹一個我覺得更易於理解的簡單情況的假結構。

1.await后所有的代碼被分離到另一個方法。

2.我們使用一個新版本叫做DownloadStringTaskAsync的DownloadString方法,它做和原版相同的事情,但它是異步的。

3.這意味着我們可以給它新的第二種方法,即在它完成時它會調用。我們使用一些“魔法”來做這件事,稍后我會告訴你。

4.當下載結束,它將會把我們調用回來帶着已經下載好的可以使用的string字符串,在這種情況下,寫到控制台。

//這就是await分解的方法,上文所說的假的結構(譯者博客園蝸牛注解)
private void DumpWebPageAsync(string uri)
{
WebClient webClient = new WebClient();
webClient.DownloadStringTaskAsync(uri)<- magic(SecondHalf);  //魔力的方法調回來
}
private void SecondHalf(string awaitedResult)
{
string page = awaitedResult;
Console.WriteLine(page);
}

   當它運行此代碼時,調用線程會發生什么?當線程抵達DownloadStringTaskAsync方法,下載工作開始,但並不在此線程中執行,在這個線程上,我們抵達了方法的結尾或者說是return,這個線程下一步做什么由我們調用者來決定。如果是UI線程,它將會返回執行用戶操作,除此外,它的資源將會被釋放,這意味着我們在做異步編程!

 
異步編程並不能解決所有問題

    異步代碼被微軟編譯器開發團隊盡可能設計的像你常寫的阻塞(同步)代碼,我們可以把耗時操作或者遠程操作處理地像本地操作和快速。但是保持和異步調用一樣的性能和優勢。

   然而,這樣的設計不是讓你忘記Async是后台操作還有發生回調。你需要小心很多事情,包括:

·異常和try-catch-finally模塊

·方法的返回值

·線程和上下文

·性能

   如果不了解它真正發生了什么,你的應用程序可能會意想不到的掛掉,並且你將無法理解異常信息和沒有能力去解決問題。

 

寫在最后  

 終於翻譯好了第一章,四頁,花了幾個小時。昨天讀了一遍,沒讀懂,今天翻譯一遍果然收獲頗多。如果您表示支持,給個贊吧!繼續閱讀下一章 我們有什么理由使用Async異步編程

 

如果我的點滴分享對您有點低幫助,歡迎點擊下方紅色關注,我將持續分享,共同進步

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM