调用Page.RegisterAsyncTask()的异步页

📅 2026/7/4 15:05:28
调用Page.RegisterAsyncTask()的异步页
我一直认为ASP.NET程序也是一种服务程序它要对客户端浏览器发出的请求而服务。 由于是服务对于要服务的对象来说都希望能尽快地得到响应这其实也是对服务的一个基本的要求 那就是高吞量地快速响应。对于前面所说的方法显然它的所有异步任务都是串行执行的对于客户端来说等待的时间会较长。 而且最严重的是如果服务超时上面的方法会一直等待直到本次请求超时。 为了解决这二个问题ASP.NET定义了一种异步任务类型PageAsyncTask 。它可以解决以上二种问题。 首先我们还是来看一下PageAsyncTask类的定义说明这个类的关键就是它的构造函数// 摘要: // 使用并行执行的指定值初始化 System.Web.UI.PageAsyncTask 类的新实例。 // // 参数: // state: // 表示任务状态的对象。 // // executeInParallel: // 指示任务能否与其他任务并行处理的值。 // // endHandler: // 当任务在超时期内成功完成时要调用的处理程序。 // // timeoutHandler: // 当任务未在超时期内成功完成时要调用的处理程序。 // // beginHandler: // 当异步任务开始时要调用的处理程序。 // // 异常: // System.ArgumentNullException: // beginHandler 参数或 endHandler 参数未指定。 public PageAsyncTask(BeginEventHandler beginHandler, EndEventHandler endHandler, EndEventHandler timeoutHandler, object state, bool executeInParallel);注意这个构造函数的签名它与AddOnPreRenderCompleteAsync()相比多了二个参数EndEventHandler timeoutHandler, bool executeInParallel 。 它们的含义上面的注释中有说明这里只是提示您要注意它们而已。创建好一个PageAsyncTask对象后只要调用页面的RegisterAsyncTask()方法就可以注册一个异步任务。 具体用法可参考我的如下代码注意代码中的注释protected void button1_click(object sender, EventArgs e) { Trace.Write(button1_click ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); // 准备回调数据它将由PageAsyncTask构造函数的第四个参数被传入。 MyHttpClientstring, string http new MyHttpClientstring, string(); http.UserData textbox1.Text; // 创建异步任务 PageAsyncTask task new PageAsyncTask(BeginCall, EndCall, TimeoutCall, http); // 注册异步任务 RegisterAsyncTask(task); } private IAsyncResult BeginCall(object sender, EventArgs e, AsyncCallback cb, object extraData) { // 在这个方法中 // sender 就是 this // e 就是 EventArgs.Empty // cb 是ASP.NET定义的一个委托我们只管在异步调用它时把它用作回调委托就行了。 // extraData 就是PageAsyncTask构造函数的第四个参数 Trace.Warn(BeginCall ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); MyHttpClientstring, string http (MyHttpClientstring, string)extraData; // 开始一个异步调用。 return http.BeginSendHttpRequest(ServiceUrl, (string)http.UserData, cb, http); } private void EndCall(IAsyncResult ar) { // 到这个方法中表示一个任务执行完毕。 // 参数 ar 就是BeginCall的返回值。 Trace.Warn(EndCall ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); MyHttpClientstring, string http (MyHttpClientstring, string)ar.AsyncState; string str (string)http.UserData; try { // 结束异步调用获取调用结果。如果有异常也会在这里抛出。 string result http.EndSendHttpRequest(ar); labMessage.Text string.Format({0} {1}, str, result); } catch( Exception ex ) { labMessage.Text string.Format({0} Error: {1}, str, ex.Message); } } private void TimeoutCall(IAsyncResult ar) { // 到这个方法就表示任务执行超时了。 Trace.Warn(TimeoutCall ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); MyHttpClientstring, string http (MyHttpClientstring, string)ar.AsyncState; string str (string)http.UserData; labMessage.Text string.Format({0} Timeout., str); }前面我说过PageAsyncTask是支持超时的那么它的超时功能是如何使用的呢上面的示例只是给了一个超时的回调委托而已。在开始演示PageAsyncTask的高级功能前有必要说明一下示例所调用的服务端代码。 本示例所调用的服务是【C#客户端的异步操作】中使用的演示服务 服务代码如下[MyServiceMethod] public static string ExtractNumber(string str) { // 延迟3秒模拟一个长时间的调用操作便于客户演示异步的效果。 System.Threading.Thread.Sleep(3000); if( string.IsNullOrEmpty(str) ) return str IsNullOrEmpty.; return new string((from c in str where Char.IsDigit(c) orderby c select c).ToArray()); }下面的示例我将演示开始二个异步任务并设置异步页的超时时间为4秒钟。protected void button1_click(object sender, EventArgs e) { Trace.Write(button1_click ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); // 设置页面超时时间为4秒 Page.AsyncTimeout new TimeSpan(0, 0, 4); // 注册第一个异步任务 MyHttpClientstring, string http new MyHttpClientstring, string(); http.UserData textbox1.Text; PageAsyncTask task new PageAsyncTask(BeginCall, EndCall, TimeoutCall, http); RegisterAsyncTask(task); // 注册第二个异步任务 MyHttpClientstring, string http2 new MyHttpClientstring, string(); http2.UserData T2_ Guid.NewGuid().ToString(); PageAsyncTask task2 new PageAsyncTask(BeginCall2, EndCall2, TimeoutCall2, http2); RegisterAsyncTask(task2); }此页面的执行过程如下确实第二个任务执行超时了。再来看一下PageAsyncTask所支持的任务的并行执行是如何调用的protected void button1_click(object sender, EventArgs e) { Trace.Write(button1_click ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); // 设置页面超时时间为4秒 Page.AsyncTimeout new TimeSpan(0, 0, 4); // 注册第一个异步任务 MyHttpClientstring, string http new MyHttpClientstring, string(); http.UserData textbox1.Text; PageAsyncTask task new PageAsyncTask(BeginCall, EndCall, TimeoutCall, http, true /*注意这个参数*/); RegisterAsyncTask(task); // 注册第二个异步任务 MyHttpClientstring, string http2 new MyHttpClientstring, string(); http2.UserData T2_ Guid.NewGuid().ToString(); PageAsyncTask task2 new PageAsyncTask(BeginCall2, EndCall2, TimeoutCall2, http2, true /*注意这个参数*/); RegisterAsyncTask(task2); }此页面的执行过程如下图片清楚地反映出这二个任务是并行执行时所以这二个任务能在4秒内同时执行完毕。在结束对PageAsyncTask的介绍前有必要对超时做个说明。 对于使用PageAsyncTask的异步页来说有二种方法来设置超时时间1. 通过Page指令 asyncTimeout0:00:45 这个值就是异步页的默认值。至于这个值的含义我想您应该懂的。2. 通过设置 Page.AsyncTimeout new TimeSpan(0, 0, 4); 这种方式。示例代码就是这种方式。注意由于AsyncTimeout是Page级别的参数因此它是针对所有的PageAsyncTask来限定的并非每个PageAsyncTask的超时都是这个值。