麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > C# > 正文

C#5.0的新特性:異步編程

2023-05-17 11:41:54
字體:
來源:轉載
供稿:網友

在即將到來的新的Windows Runtime(Windows 運行時)中更根本地確定任何API都不會運行超過50ms的時間。需要更長時間的操作將會由'kick off this operation'API來代替,不等待運算結果就直接立刻返回。這樣做是因為微軟希望Windows8 Metro程序能夠在即時的觸控UI(用戶界面)上能夠“快速并且流動”,因為觸控操作上即使是微小的停頓相比于用鼠標或者鍵盤來操作都會變得更加明顯。從UI的角度來說,這是一項很有幫助的設計方案。

但是從開發者的角度來說,它會使編程變得更加麻煩。當我們讀取文件或者調用WCF服務時,我們通常希望能夠影響到結果。如果能夠保證讀取文件或者WCF服務返回時結果肯定可獲得的,我們由上而下地寫出容易理解和推理的代碼。

string url = ReadUrlFromFile(filename);
string contentOfUrl = HttpGetFromUrl(url);
MessageBox.Show(contentOfUrl);

這樣的API被叫做同步或者阻塞。同步API易于理解和使用,不過在你的程序內部當前線程沒有反應時,API就無法控制你的代碼去做其它任務,因為它還不能傳遞結果。

擁使用即時返回的'kick off' API的方式叫做異步或者無阻塞。使用異步API編程更加繁難,因為你不能即時將結果返回給變量來保證運行:

string url = BeginReadUrlFromFile(filename); // Won't work -- file read hasn't completed when BeginRead returns
string contentOfUrl = BeginHttpGetFromUrl(url); // Ditto
MessageBox.Show(contentOfUrl);

相反,你不得不回調需要使用返回結果的代碼,直到它已經準備好了:

BeginReadUrlFromFile(filename, url => {
BeginHttpGetFromUrl(url, contentOfUrl => {
MessageBox.Show(contentOfUrl);
});
});

甚至于這樣一個簡單的例子都顯得相當丑陋。實際上,異步代碼中需要更多的運算,更復雜的回調,邏輯條件,early exits以及錯誤處理,所以會更加難看。.NET框架中真正的異步API更加丑陋,到處都是 IAsyncResult對象和成對的EndXxx方法調用。

然而,如果我們希望能程序在Windows Runtime中運行,這就是用戶所希望我們做的。

原來的解決方案:使用F#

F#背后聰明的人們想出來一個兩全其美的解決方案。F#有一個叫做異步工作流程的特色功能,它由很多塊異步引進的代碼塊組成。在異步工作流程中,你可以通過使用一個很像同步的語法來調用異步方法:

async {
let! url = BeginReadUrlFromFile filename
let! contentOfUrl = BeginHttpGetFromUrl url
MessageBox.Show(contentOfUrl)
}

F#編譯器自動將這易于閱讀、理解的代碼轉變為可怕的回調式等價物,這樣你就可以簡單地使用異步調用的響應行為從上而下地編程。

新的解決方案:使用C# 5

C#背后也有同樣聰明的人,所以新的C#中也實現了這項功能。Visual Studio 11 beta中包含的下一版本的C#進了兩個新關鍵字——"async" 和 "await"

關鍵字"async"表明使用的是異步調用方法。這對于調用者來說,理解它非常重要,因為這意味著方法會在它結束前返回——方法能夠在異步調用時中途放棄而直接返回給它的調用者。

關鍵字"await"表明我們希望保證自上而下的邏輯 異步調用 而不是手動編寫回調函數。下面是他們完美結合在一起的例子:

public async void ShowReferencedContent(string filename) {
string url = await BeginReadFromFile(filename);
string contentOfUrl = await BeginHttpGetFromUrl(url);
MessageBox.Show(contentOfUrl);
}

這樣比回調更方便讀、寫和檢查,但他們的作用完全相同。(實際上,這確實比回調更智能些,因為編譯器并不會因為厭煩而跳過錯誤狀況或者弄錯early exit邏輯又或者忽略線程錯誤。)

當我們調用方法時發生了什么?首先是調用BeginReadFromFile方法,它提供了文件名和編譯器生成的回調。BeginReadFromFile迅速返回,但結果仍然不可得。所以結果仍然不能分配給URL變量——回調的一部分——然后方法退出,返回給調用者!調用函數重新運行,并且保持它的代碼持續運行,盡管被調用方法還沒有結束。

然后在晚點時候,文件系統完成了閱讀操作。這意味著結果現在是可獲得的,Runtime安排回調。這并不一定會立刻發生——具體的時間還依賴于同步的環境。回調函數運行著,捆將URL變量和文件操作的結果綁定,然后調用BeginHttpGetFromUrl。它也會立刻返回,也就是說,方法會再一次退出。

最后,HTTP操作完成,回調函數第二次運行。它將綁定Url變量的內容和顯示結果的消息框如果(如果有的話)。

我會希望向調用者返回什么值?

Async methods can exit before they’ve finished. So if an async method wants to return a result, it has to recognise that it might return to the caller before that result is available. For this reason, an async method that returns a value has to have a return type of Task rather than a ‘proper’ value. A Task represents a chunk of work which will eventually deliver a value, so a caller can examine the returned Task to determine when the result becomes available. Here’s how an async method looks when returning a value:

異步方法能夠在結束前退出,所以,如果一個異步方法希望返回一個結果就不得不確認它是否在得到結果前就返回給調用者。因此,一個返回值的異步方法不得不包含一個Task返回類型而不是一個“合適的”值。一個Task代表最終會傳遞值的很大一塊工作,所以調用者也能堅持返回的Task來確定什么時候會得到結果。下面是一個返回值的異步方法的樣子:

public static async Task<string> GetReferencedContent(string filename)
{
  string url = await BeginReadFromFile(filename);
  string contentOfUrl = await BeginHttpGetFromUrl(url);
  return contentOfUrl;
}

注意:盡管返回類型是Task<string>,返回狀態接收的是一條字符串。再一次,編譯器來管理返回狀態產生一個Task。

現在調用者能夠直接調用GetReferencedContent方法或者等待字符串變為可得,或者手動讓它等待,又或者使它提前結束——無論如何它都適合使用結果。

Async-friendly APIs

如果你習慣在.NET 4或者更早之前版本上使用異步編程,你會習慣成對地使用Begin和End方法,比如WebRequest.BeginGetResponse 和WebRequest.EndGetResponse。這在.NET4.5中依然存在,但它們不使用await關鍵字。(主要是因為BeginXxx方法需要在回調中使用確切的方法調用來得到結果,而且編譯器并不依賴EndXxx命名規范).NET4.5提供了返回Task對象的新方法,所以你可以調用WebRequest.GetResponseAsync來代替WebRequest.BeginGetResponse方法。下面是一個.NET4.5中使用異步API的一個實例:

private static async Task<string> GetContent(string url)
{
   WebRequest wr = WebRequest.Create(url);
   var response = await wr.GetResponseAsync();
   using (var stm = response.GetResponseStream())
   {
     using (var reader = new StreamReader(stm))
     {
       var content = await reader.ReadToEndAsync();
       return content;
     }
   }
}

這和使用 WebRequest.GetResponse() 和 TextReader.ReadToEnd()的同步代碼是如此相似,只需要在API名后加上Async并且在方法前加上"await"關鍵字就可以了,相信你很快就能掌握它。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 亚洲日色 | 国av在线| a视频在线播放 | 国产精品久久久久久久av三级 | 成人男女啪啪免费观看网站四虎 | 欧美日韩经典在线 | 免费国产视频大全入口 | 成人h视频在线 | 91九色网址 | 国产精品刺激对白麻豆99 | 亚洲国产精品一区二区久久 | 国产精品成人久久久久a级 av电影在线免费 | www.国产一区.com | 国产精品99久久久久久久女警 | 欧美一区二区精品夜夜嗨 | 欧美中文字幕在线视频 | 娇妻被各种姿势c到高潮小说 | 一级黄色毛片播放 | 国内精品久久久久久久影视红豆 | 九九黄色 | 毛片国产 | 国产精品视频一区二区三区综合 | 成人午夜免费观看 | 国产九九热视频 | 精品免费久久 | 特片网久久 | 欧美一级视频免费看 | chinesexxxx刘婷hd 国产资源视频在线观看 | 中国字幕av | 舌头伸进添的我好爽高潮网站 | sese在线视频| 羞羞网站视频 | 久久久精品福利 | 一本色道久久久888 国产一国产精品一级毛片 国产精品高潮视频 | 欧洲黄色一级视频 | 男人的天堂色偷偷 | 亚洲射逼| 日韩视频不卡 | 99亚洲国产精品 | 99在线热播精品免费 | 在线亚洲欧美日韩 |