之前看過老趙這兩篇文章。也研究了一下老趙非同步實現方式。
不過感覺自己擴充的話,在ASP.NET MVC中使用非同步還真是麻煩,剛好看到從RC1版開始 ASP.NET MVC Futures中提供了幾個支援非同步類。
相關的類包括AsyncActionDescriptor、AsyncController、AsyncControllerActionInvoker、AsyncManager、AsyncResultWrapper、AsyncTimeoutAttribute、NoAsyncTimeoutAttribute,相關介面有IAsyncActionDescriptor、IAsyncActionInvoker、IAsyncController、IAsyncManagerContainer。
下面說一下怎麼用它們
一、使用非同步Action前的準備工作
1.引用Microsoft.Web.Mvc。
2.先要將要非同步處理的Url交由MvcHttpAsyncHandler處理,這一步可以由AsyncRouteCollectionExtensions.MapAsyncRoute來設定規則,將原MapRoute處理的規則改為MapAsyncRoute,如:
routes.MapAsyncRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } );
3.將相應的Controller繼承於AsyncController。
public class HomeController : AsyncController { }
4.我們約定以下定義的Action都在HomeController中
二、第一種非同步Action方式:Action、ActionCompleted方式
ASP.NET MVC Futures支援按名稱自動尋找非同步Action的方法
Url:/Home/Async1
其使用方法為
public void Async1(){ //主線程 } public ActionResult Async1Completed(){ //自動尋找與主線程 Action名稱+Completed 的Action 做為非同步Action return Content("Async1"); }
三、第二種非同步Action方式:BeginAction、EndAction方式
如果第一種方式你瞭解了的話第二種自然也不在話下,不過這種方式是與其它類的非同步呼叫一起使用。
Url:/Home/Async2
public delegate void AsyncEventHandler();//我這裡自己聲明了一個委託,也可以使用WebRequest/WebResponse/SqlConnection來實現這個非同步過程 public void Event1(){} public IAsyncResult BeginAsync3(AsyncCallback callback, object state){ AsyncEventHandler asy = new AsyncEventHandler(Event1); ViewData["a"]=asy;//這裡在方法間傳值必須使用輔助儲存物件,第一種方法中也是一樣 return asy.BeginInvoke(callback, state); } public void EndAsync3(IAsyncResult result){//轉到非同步Action中 var a = ViewData["a"] as AsyncEventHandler; a.EndInvoke(result); Content("完成").ExecuteResult(this.ControllerContext); }
四、第三種非同步Action方式:使用AsyncManager.RegisterTask及委託
如果感覺上面使用2個方法才能實現非同步Action有些麻煩的話(也的確是麻煩),可以使用AsyncManager.RegisterTask來調用委託來實現非同步呼叫。
Url:/Home/Async3
public void Async2(){ this.AsyncManager.RegisterTask(c => { //主線程,調用非同步線程 c(null); }, delegate(IAsyncResult result) { //非同步部分 Content("Async2").ExecuteResult(this.ControllerContext); }); }
其實無論是哪種方法都感覺不太完美,我個人覺得Action/ActionCompleted的方法可能更優美一點,適合一般使用(只是這三個比較)。只是AsyncManager.RegisterTask的方法傳值方便一點,而Begin/End方法更適合與其它非同步操作配合。
當然本文還有肯定還有好多地方沒有講到,包括其它的非同步呼叫方式還有Filter,所以希望朋友們多多討論。
附老趙2個文章
為ASP.NET MVC擴充非同步Action功能(上)
為ASP.NET MVC擴充非同步Action功能(下)
我的ASP.NET MVC系列:Asp.net Mvc Framework 系列