news 2026/7/4 15:05:22

调用Page.RegisterAsyncTask()的异步页

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
调用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构造函数的第四个参数被传入。 MyHttpClient<string, string> http = new MyHttpClient<string, 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()); MyHttpClient<string, string> http = (MyHttpClient<string, 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()); MyHttpClient<string, string> http = (MyHttpClient<string, 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()); MyHttpClient<string, string> http = (MyHttpClient<string, 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); // 注册第一个异步任务 MyHttpClient<string, string> http = new MyHttpClient<string, string>(); http.UserData = textbox1.Text; PageAsyncTask task = new PageAsyncTask(BeginCall, EndCall, TimeoutCall, http); RegisterAsyncTask(task); // 注册第二个异步任务 MyHttpClient<string, string> http2 = new MyHttpClient<string, 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); // 注册第一个异步任务 MyHttpClient<string, string> http = new MyHttpClient<string, string>(); http.UserData = textbox1.Text; PageAsyncTask task = new PageAsyncTask(BeginCall, EndCall, TimeoutCall, http, true /*注意这个参数*/); RegisterAsyncTask(task); // 注册第二个异步任务 MyHttpClient<string, string> http2 = new MyHttpClient<string, string>(); http2.UserData = "T2_" + Guid.NewGuid().ToString(); PageAsyncTask task2 = new PageAsyncTask(BeginCall2, EndCall2, TimeoutCall2, http2, true /*注意这个参数*/); RegisterAsyncTask(task2); }

此页面的执行过程如下:

图片清楚地反映出,这二个任务是并行执行时,所以,这二个任务能在4秒内同时执行完毕。

在结束对PageAsyncTask的介绍前,有必要对超时做个说明。 对于使用PageAsyncTask的异步页来说,有二种方法来设置超时时间:
1. 通过Page指令: asyncTimeout="0:00:45" ,这个值就是异步页的默认值。至于这个值的含义,我想您应该懂的。
2. 通过设置 Page.AsyncTimeout = new TimeSpan(0, 0, 4); 这种方式。示例代码就是这种方式。
注意:由于AsyncTimeout是Page级别的参数,因此,它是针对所有的PageAsyncTask来限定的,并非每个PageAsyncTask的超时都是这个值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 15:03:53

Python+OpenCV实现文档图像自动矫正技术

1. 项目背景与核心价值 去年帮朋友公司处理报销单据时&#xff0c;我发现财务同事每天要手动调整上百张手机拍摄的倾斜发票。这些图像存在各种透视变形&#xff1a;有的四角不齐&#xff0c;有的边缘弯曲&#xff0c;还有的因为拍摄角度产生梯形失真。传统方法是用Photoshop手动…

作者头像 李华
网站建设 2026/7/4 15:03:46

基于YOLOv8的无人机目标检测系统开发实战

1. 项目概述&#xff1a;无人机目标检测系统开发 去年参与了一个智慧城市安防项目&#xff0c;其中最关键的需求就是实现对"黑飞"无人机的实时监测。传统雷达方案在复杂城市环境中误报率高达30%&#xff0c;我们团队最终选择了基于YOLO系列的视觉检测方案。这套系统从…

作者头像 李华
网站建设 2026/7/4 15:03:31

多维聚合中的数据操作:Rollup、Drilldown、Slice、Dice实战体系

1. 这不是“高级SQL技巧”&#xff0c;而是数据工程师每天要拆解的现实问题 你有没有遇到过这样的场景&#xff1a;业务方发来一张Excel表格&#xff0c;里面是“各区域、各产品线、各季度的销售额毛利客户数复购率”&#xff0c;要求你“按月看趋势、按年做对比、按大区拉总、…

作者头像 李华
网站建设 2026/7/4 15:01:14

企业AI落地:自上而下与自下而上策略的实战选择指南

1. 这不是一场理论辩论&#xff0c;而是每天都在发生的资源争夺战 “Unleashing the Power of AI/ML in Enterprises — A Battle between Top-Down and Bottom-Up Strategies”——这个标题里没有一个生僻词&#xff0c;但每个词都带着沉甸甸的现实重量。我从2014年开始带团队…

作者头像 李华
网站建设 2026/7/4 14:57:56

HAJIMI:零配置部署高可用AI代理网关,实现Gemini API智能管理

1. 项目概述&#xff1a;HAJIMI&#xff0c;一个让AI服务部署变简单的“智能管家” 如果你正在用Gemini API开发AI应用&#xff0c;大概率遇到过这样的场景&#xff1a;深夜&#xff0c;你的智能客服机器人突然哑火&#xff0c;用户反馈像雪花一样涌来&#xff0c;你手忙脚乱地…

作者头像 李华
网站建设 2026/7/4 14:57:39

Android应用安全加固实战:从InsecureBankv2漏洞修复到安全开发实践

1. 项目概述&#xff1a;从“漏洞百出”到“固若金汤”的实战之旅如果你是一名Android开发者&#xff0c;或者对移动安全感兴趣&#xff0c;那么你一定听说过或者亲手搭建过InsecureBankv2这个经典的“反面教材”。它不是一个真正的银行应用&#xff0c;而是一个故意设计得漏洞…

作者头像 李华