使用ASP.NET MVC Futures 中的非同步Action
之前看過老趙這兩篇文章。也研究了一下老趙非同步的實現方式。
不過感覺自己擴充套件的話,在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的方法
其使用方法為
publicvoid Async1(){ //主執行緒 } public ActionResult Async1Completed(){ //自動尋找與主執行緒 Action名稱+Completed 的Action 做為非同步Action return Content("Async1"); }
三、第二種非同步Action方式:BeginAction、EndAction方式
如果第一種方式你瞭解了的話第二種自然也不在話下,不過這種方式是與其它類的非同步呼叫一起使用。
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來呼叫委託來實現非同步呼叫。
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個文章