写在前面
有个小项目,前端使用的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的文章,另外手上也有一个项目,就想着能不能使用异步的方式。所以就有了这篇文章。