偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

F#與ASP.NET:基于事件的異步模式與異步Action

開發(fā) 開發(fā)工具 后端
提高ASP.NET應(yīng)用程序伸縮性的有效手段之一便是使用異步請求,而在ASP.NET MVC 1中是不能直接支持異步Action的,因此我們需要使用一些簡單的Hack方式來實現(xiàn)這一點。

盡管在ASP.NET MVC 1中是不能直接支持異步Action,但在ASP.NET MVC 2中已經(jīng)正式支持ASP.NET中的異步請求處理方式,并且通過一種比較易于使用的方式提供給開發(fā)人員使用。只可惜,由于語言層面的約束,這種使用方式還是有些不便,而此時便是F#的用武之地了。

基于事件的異步模式

說起.NET中的異步編程模型,.NET程序員最熟悉的應(yīng)該就是Begin/End方法了。例如在WebRequest類中,便有這樣一對方法:

  1. var request = WebRequest.Create("http://www.szyisi.cn/");  
  2. request.BeginGetResponse(ar => 
  3. {  
  4.     var response = request.EndGetResponse(ar);  
  5.     // use the response object  
  6.  
  7. }, null);  

在調(diào)用WebRequest對象的BeginGetResponse方法之后,當(dāng)前調(diào)用線程不會被阻塞,而在異步操作完成之后,便會調(diào)用一個回調(diào)函數(shù)(即這里使用Lambda表達(dá)式構(gòu)造的代碼快)進(jìn)行通知,在這個回調(diào)函數(shù)中調(diào)用EndGetResponse方法便可以得到一個WebResponse對象作為結(jié)果。

在這個異步操作中,由于偉大的IOCP,我們可以使用極少數(shù)的線程同時發(fā)起成千上萬個連接(豪不夸張,我曾經(jīng)在IIS里進(jìn)行Comet試驗,同時建立起超過2w個連接進(jìn)行通信)。不過,事實上在.NET中還有一種基于事件的異步模式(Event-based Asynchronous Pattern,EAP)?;谑录漠惒骄幊痰牡湫桶咐槐闶荳ebClient類:

  1. var client = new WebClient();  
  2. client.DownloadStringCompleted += (sender, args) => 
  3. {  
  4.     var html = args.Result;  
  5.     // ...  
  6. };  
  7.  
  8. client.DownloadStringAsync(new Uri("http://www.szyisi.cn/"));  

基于事件的異步模式的關(guān)鍵便在于,它是使用事件來作為工作結(jié)束時的通知機制。它和Begin/End的異步模型有明顯區(qū)別。例如,在發(fā)生錯誤時,對于Begin/End模型來說會在End方法調(diào)用時拋出異常,而對于基于事件的異步模式來說,它則是使用事件參數(shù)的Exception屬性來告訴程序員是否有異常發(fā)生。如果Exception屬性為null,則說明一切正常,否則它便返回異步調(diào)用過程中發(fā)生的異常。

在ASP.NET MVC中使用異步Action

當(dāng)年我的Hack使用的是Begin/End異步編程模型,而ASP.NET MVC 2則使用了基于事件的異步模式。圍繞這種模式,ASP.NET MVC的AsyncController還提供了相關(guān)的輔助方法,讓異步Action的編寫變得相對容易一些。這里我則直接引用MSDN上的示例來說明問題。首先,我們準(zhǔn)備一個普通的同步Action:

 

  1. public class PortalController : Controller  
  2. {  
  3.     public ActionResult News(string city)  
  4.     {  
  5.         var newnewsService = new NewsService();  
  6.         var headlines = newsService.GetHeadlines(city);  
  7.         return View(headlines);  
  8.     }  

與它等價的異步Action則為:

  1. public class PortalController : AsyncController  
  2. {  
  3.     public void NewsAsync(string city)  
  4.     {  
  5.         AsyncManager.OutstandingOperations.Increment();  
  6.  
  7.         var newnewsService = new NewsService();  
  8.         newsService.GetHeadlinesCompleted += (sender, e) => 
  9.         {  
  10.             AsyncManager.Parameters["headlines"] = e.Value;  
  11.             AsyncManager.OutstandingOperations.Decrement();  
  12.         };  
  13.  
  14.         newsService.GetHeadlinesAsync(city);  
  15.     }  
  16.  
  17.     public ActionResult NewsCompleted(string[] headlines)  
  18.     {  
  19.         return View("News", headlines);  
  20.     }  
  21. }  

很顯然,異步Action也是標(biāo)準(zhǔn)的二段式調(diào)用,不過這個二段式調(diào)用卻由比較特別的“約定”。在ASP.NET MVC 2中使用異步Action時,首先需要繼承AsyncController類,并構(gòu)造XyzAsync及XyzCompleted兩個方法,前者返回void,后者返回ActionResult——這便表示一個異步的Action,名為Xyz。

ASP.NET MVC 2中對于異步Action的開發(fā)也提供了一定支持,這個支持便來自于AsyncManager。在發(fā)起異步操作之前,我們可以調(diào)用其OutstandingOperations對象的Increment方法,表示需要“進(jìn)行幾次異步操作”。

而每次異步操作結(jié)束之后,也就是在事件的處理函數(shù)中,便會調(diào)用對應(yīng)的Decrement方法。這個方法表示“完成了一次異步操作”,而Decrement至零之后ASP.NET MVC便會得知所有的異步操作已經(jīng)完成,于是便會調(diào)用XynCompleted方法,得到所需的ActionResult對象。

至于XyzCompleted方法所需要的參數(shù),從代碼中便可看出是通過AsyncManager的Parameters集合進(jìn)行“過渡”的。這里有個不是很理想的地方,便是使用了字符串這種“弱類型”的方式,假設(shè)參數(shù)名改變,則對應(yīng)的字符串也需要跟著改變。

選擇Begin/End還是基于事件的異步模式?

很顯然,在ASP.NET MVC中使用既可以使用Begin/End或是基于事件的異步編程模式,因為ASP.NET MVC本身只是根據(jù)AsyncManager的行為來進(jìn)行異步操作。不過在ASP.NET MVC中,似乎更看重的是基于事件的異步模式。我估計,這是由于兩種異步模式對于異常的行為差異所造成的吧。

正如我之前所提到的那樣,在使用Begin/End異步模式時,如果出現(xiàn)了錯誤則會在End方法調(diào)用時拋出異常。要知道在回調(diào)函數(shù)中拋出異常是異步編程中最危險的情況(有沒有之一?),如果沒有正確地進(jìn)行捕獲則會讓整個進(jìn)程崩潰——當(dāng)然,我們也可以在配置文件中設(shè)置成“忽略”,但是這明顯也不妥當(dāng),例如會造成請求永遠(yuǎn)無法結(jié)束,直至超時,并且有可能造成資源泄露。

與之相對,使用基于事件的異步模式則不會出現(xiàn)這個問題,因為在這種情況下,事件一定會被正確調(diào)用,而異常則永遠(yuǎn)安安穩(wěn)穩(wěn)地保存在事件參數(shù)的Exception屬性中。因此,使用Begin/End則需要額外的try...catch進(jìn)行保護(hù),使用基于事件的異步編程模式則會讓代碼變得精簡一些。

當(dāng)然,用著簡單,也只是因為那些異常已經(jīng)被異步操作的“提供方”給處理了。試想,WebClient之所以可以通過事件參數(shù)來暴露異常,一定是因為在它內(nèi)部使用了try...catch。同理,如果我們要實現(xiàn)一個基于事件的異步模式,例如上面的NewsService,那也一定少不了對異常進(jìn)行仔細(xì)處理。

【編輯推薦】

  1. 詳細(xì)介紹Visual Studio 2010F#使用
  2. 對Visual Studio 2010F#代碼介紹
  3. TechED 09視頻專訪:F#與函數(shù)式編程語言
  4. 詳解F#異步及并行模式中的并行CPU及I/O計算
責(zé)任編輯:王曉東 來源: 老趙的博客
相關(guān)推薦

2010-04-07 16:51:59

F#

2009-07-22 10:13:31

異步ActionASP.NET MVC

2009-03-06 10:28:30

MVCASP.NET異步Action

2010-03-26 19:03:19

F#異步并行模式

2009-02-17 09:22:14

ActionMVCASP.NET

2009-02-16 10:05:11

ActionMVCASP.NET

2009-07-28 16:40:11

ASP.NET異步頁面

2012-03-31 10:59:02

ASP.NET

2013-04-01 15:25:41

異步編程異步EMP

2009-08-21 17:02:20

ASP.NET異步回調(diào)

2011-11-22 09:32:39

ASP.NET

2013-03-08 09:33:25

JavaScript同步異步

2012-07-04 14:49:34

ASP.NET

2010-03-26 18:31:59

F#異步并行模式

2010-03-16 09:09:04

F#

2009-08-21 17:11:15

ASP.NET異步回調(diào)

2009-07-29 17:29:46

ASP與ASP.NET

2009-07-22 09:11:02

Action方法ASP.NET MVC

2011-02-24 12:53:51

.NET異步傳統(tǒng)

2009-08-20 17:47:54

C#異步編程模式
點贊
收藏

51CTO技術(shù)棧公眾號