寫在前面
有個小項目,前端使用的html頁面,那服務端的業務處理就采用最簡單的一般處理程序了,之前一直在用,覺得一直用一種方式,確實挺蛋疼的,之前也有了解過async和await的內容。就想着自己折騰折騰。
代碼
前端ajax請求
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>新年簽到,贏獎品</title> </head> <body> <div id="dvMsg"></div> </body> </html> <script src="Js/jquery-2.1.1.min.js"></script> <script> $(function () { $.getJSON("Ashx/GetUserInfoAsync.ashx", function (data) { console.log(data); $('#dvMsg').html(data); }); }); </script>
一般處理程序
/// <summary> /// GetUserInfoAsync 的摘要說明 /// </summary> public class GetUserInfoAsync : IHttpHandler { public async void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; var name = await GetUserAsync(); context.Response.Write(name); } private async Task<string> GetUserAsync() { return await Task.Run(() => { return "異步handler"; }); } public bool IsReusable { get { return false; } } }
以為這樣就大功告成了。其實這才是悲劇的開始。
滿足使用async和await的條件了?
調用的目標方法必須是async的。所以就想着在ProcessRequest方法前加個async就可以了吧。其實不然,在使用async的地方也有特別的要求。
詳情
大概意思就是異步操作,只能在異步模塊中進行。所以就很奇怪了。之前在控制台程序中,也是給Main方法直接添加async的。這里就不行了。
經過查找,發現這樣的一個類
using System; using System.ComponentModel; using System.Threading.Tasks; namespace System.Web { // 摘要: // 提供方法,從而衍生的任務處理程序類可實施該方法以處理異步任務。 public abstract class HttpTaskAsyncHandler : IHttpAsyncHandler, IHttpHandler { // 摘要: // 從派生類中的構造函數中調用,用於初始化 System.Web.HttpTaskAsyncHandler 類。 protected HttpTaskAsyncHandler(); // 摘要: // 當在派生類中重寫時,將獲取一個指示任務處理程序類實例是否可重用於另一異步任務的值。 // // 返回結果: // 如果重復使用處理程序,則為 true;否則為 false。 默認值為 false。 public virtual bool IsReusable { get; } // 摘要: // 當在派生類中重寫時,將提供處理同步任務的代碼。 // // 參數: // context: // HTTP 上下文。 // // 異常: // System.NotSupportedException: // 方法實現但不提供任何默認用於異步任務的處理程序。 [EditorBrowsable(EditorBrowsableState.Never)] public virtual void ProcessRequest(HttpContext context); // // 摘要: // 當在派生類中重寫時,將提供處理異步任務的代碼。 // // 參數: // context: // HTTP 上下文。 // // 返回結果: // 異步任務。 public abstract Task ProcessRequestAsync(HttpContext context); } }
發現這個抽象類實現自IHttpAsyncHandler, IHttpHandler這兩個接口,肯定能滿足需求了。那么接下來就對一般處理程序進行改造
/// <summary> /// GetUserInfoAsync 的摘要說明 /// </summary> public class GetUserInfoAsync : HttpTaskAsyncHandler { private async Task<string> GetUserAsync() { return await Task.Run(() => { return "異步handler"; }); }public override async Task ProcessRequestAsync(HttpContext context) { context.Response.ContentType = "text/plain"; var name = await GetUserAsync(); context.Response.Write(name); } }
這樣就很方便的將一般處理程序變成一個異步處理的了。
總結
沒事折騰一下代碼,最近在博客園中看到關於await和async的文章,另外手上也有一個項目,就想着能不能使用異步的方式。所以就有了這篇文章。