你应该知道的 asp.net webform之异步页面

2024-03-17 06:48

本文主要是介绍你应该知道的 asp.net webform之异步页面,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对于搞asp.net的程序员,都知道所有的服务请求最终都会有一个IhttpHandler来处理,就像我们最常用的aspx页面。相对于IHttpHandler,asp.net还提供了一个异步的相同版本的处理程序接口,它就是IHttpAsyncHandler,同样asp.net也可以让我们的aspx页面实现IHttpAsyncHandler,而不仅仅是IHttpHandler。

 

为什么要异步页面

      我们都知道asp.net维护一个处理页面请求的线程池,每一个新的请求,asp.net就会从其中取出一个空闲的线程来实例化页面,运行处理代码然后呈现HTML,然后返回线程池,等待下一次被激活。但是如果请求到来的过于频繁,比我们线程处理页面返回时间还短,那么这个请求就会被放到一个队列里,如果队列满了,就会产生一个503的服务不可用来拒绝其它的请求。

      可以想象,如果我们的页面在等待一个慢的服务器在处理大量的数据、读取远程文件或一个WEB服务返回数据,这时我们页面没有代码要执行,但是这个线程会被挂起,这就会严重的消耗可用线程,影响网站并发。

      而通过异步页面, 我们可以把这些耗时的处理迁移到其它线程池,而这些异步工作完成时,asp.net会接到通知,再次从线程池激活一个可用线程,处理余下的工作,最终呈现HTML。

 

创建异步页面

      创建异步页面,远比我们想象简单的多,我们首先要在Page指令加一个Async的特性,并把它设为true.

1
<%@ Page Async= "true" AsyncTimeout= "60" ...

还有一个timeout的特性用来指定异步的超时时间,单位是s,默认是45s。

 

      接下来,我们需要调用AddOnPreRenderCompleteAsync注册异步处理:

1
2
3
4
protected void Page_Load( object sender, EventArgs e)
{
     AddOnPreRenderCompleteAsync( new BeginEventHandler(BeginHandler), new EndEventHandler(EndHandler));
}

 

AddOnPreRenderCompleteAsync还提供另一个重载的版本

1
2
3
4
5
public void AddOnPreRenderCompleteAsync(
     BeginEventHandler beginHandler,
     EndEventHandler endHandler,
     Object state
)

首先,开始启动异步任务的委托和处理异步结束时的回调是不可少的,另一个参数,让我们可以传递一些状态的信息给异步开始的方法。

 

异步页面的执行

       在我们展示BeginHandler、EndHandler之前,让我们通过下面转载自MSDN的一张图,看一下异步处理是如何工作的:

 

      我们可以看出我们注册的BeginHandler在prePrend之后才开始执行,这时线程已经回到线程池,代码的处理交到了BeginHandler,我们必须在这里开始一个异步的处理,处理完后返回IAsyncResult的结果,随后EndHandler被调用,之后,线程池的另一个线程被激活,接着处理页面流程。

 

有效的异步处理

      到了这里,你可能感觉到异步页面分明就是一个坑啊,到了最后还是要我们自己去实现异步处理一个耗时的操作。

     但是这可能对于我们来说算不上什么啊,我们有很多种方法开始异步的处理啊,ThreadPool.QueueUserWorkItem,Thread类创建一个专用线程、委托的BeginInvoke和类库中内建的异步支持,如Command的BeginExecuteReader,但是我们能选择的却不是那么多。

 

      第一类,委托的BeginInvoke和ThreadPool.QueueUserWorkItem,这两个会从asp.net请求线程池中激活线程来处理,这就是相同于释放一个线程的同时又从线程池拿一个线程出来,这不是脱裤子放屁吗?一点也起不到增强网站并发处理的能力,还无谓的增加了线程调度的浪费。

 

      第二类,Thread类创建专用线程,这样做可以达到目的,并且可以做到服务器不能处理的工作,但这是非常危险的。如果这样的请求过于和频繁,创建出过多的这样的线程,这对服务器是一种压力,很可能导致服务器再也不能处理其它的请求了。当然,你可以实现一个自定义的线程池来管理这些线程,让他保持在一个合适的范围,并且总是有可用的线程可用,但是这个开发代价就太大了。

 

      接下来就只有.net内置如数据Command的BeginExecuteReader、IO的BeginRead和BeginWriter等处理异步的支持了,其实这也是我们最应该也最值得用的异步方式。让.net去管理线程的问题,又不会从当前请求线程池中拿线程,使用起来也简单强大。

 

异步的实现

      接着上面的代码,我们贴出BeginHandler、EndHandler代码,只是提供一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private SqlConnection con;
private SqlCommand cmd;
private IAsyncResult BeginHandler(Object obj, EventArgs args, AsyncCallback cb, Object state)
{
     string conStr = "" ;
     con = new SqlConnection(conStr);
     cmd = new SqlCommand( "select * from ..." , con);
     con.Open();
     return cmd.BeginExecuteReader(cb, state);
}
private void EndHandler(IAsyncResult ar)
{
     try
     {
         SqlDataReader reader = cmd.EndExecuteReader(ar);
         ……………
     }
     catch (Exception ex)
     {
         //  错误处理
     }
}

 

      这样就实现了一个简单的异步页面的模型,对于这些耗时的操作,我们可能会使用到缓存,这样我们自定义一个实现了IAsyncResult的类,包含我们要使用的数据,在BeginHandler里判断缓存是否存在,如果存在返回自定义实例,并用缓存填充这个实例,不存在就执行异步操作;而在EndHandler里区分出返回实例,使用数据再更新缓存。

 

多异步任务

     如果要处理多个Web服务或者同时去等待web服务,还有数据库操作等等,这时,我们怎么做?

 

1,我们可以调用多次AddOnPreRenderCompleteAsync,每次传入对应的begin和end的委托,但是注册的多个任务是顺序执行的,也就是只有处理完第一个任务end执行过后,才会开始执行第二个任务。

 

2,我们只调用一次AddOnPreRenderCompleteAsync,在begin里启动多少异步操作,但是这个操作会有太多的局限性,并且会更复杂。

 

3,不出大家意外,asp.net提供了处理这样的方法。就是如下的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PageAsyncTask taska = new PageAsyncTask(
     new BeginEventHandler(BeginHandler1),
     new EndEventHandler(EndHandler1),
     null ,
     null
     );
Page.RegisterAsyncTask(taska);
PageAsyncTask taskb = new PageAsyncTask(
     new BeginEventHandler(BeginHandler2),
     new EndEventHandler(EndHandler2),
     null ,
     null
     );
Page.RegisterAsyncTask(taskb);

这样的注册异步任务会同时执行,当所有的异步都执行完毕,才会开始余下的页面的流程。

 

最后我们看一下PageAsyncTask的重载版本:

1
2
3
4
5
6
7
public PageAsyncTask (
     BeginEventHandler beginHandler,
     EndEventHandler endHandler,
     EndEventHandler timeoutHandler,
     Object state,
     bool executeInParallel
)

除了前两个任务开始和结束调用操作参数之外,还提供了一个超时时的处理程序、一个球表示任务状态的对象和一个是否要和其它任务同时执行的布尔值。

 

最后

没有最好,只有最适合,任何一种的处理方式都不会是完美的,就像Jeffrey大师在异步操作中所说的:应尽可能限制线程的使用。异步页面虽然可以让我们网站可以处理更多的请求,但是它并不会让你的用户感觉到页面的呈现变快,甚至会慢些,因为创建线程本身就会产生一定的消耗,并且线程之间的切换开销也相当大。切记。


这篇关于你应该知道的 asp.net webform之异步页面的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/818153

相关文章

SpringBoot全局异常拦截与自定义错误页面实现过程解读

《SpringBoot全局异常拦截与自定义错误页面实现过程解读》本文介绍了SpringBoot中全局异常拦截与自定义错误页面的实现方法,包括异常的分类、SpringBoot默认异常处理机制、全局异常拦... 目录一、引言二、Spring Boot异常处理基础2.1 异常的分类2.2 Spring Boot默

C#借助Spire.XLS for .NET实现在Excel中添加文档属性

《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

Python结合Free Spire.PDF for Python实现PDF页面旋转

《Python结合FreeSpire.PDFforPython实现PDF页面旋转》在日常办公或文档处理中,我们经常会遇到PDF页面方向错误的问题,本文将分享如何用Python结合FreeSpir... 目录基础实现:单页PDF精准旋转完整代码代码解析进阶操作:覆盖多场景旋转需求1. 旋转指定角度(90/27

使用Python实现在PDF中添加、导入、复制、移动与删除页面

《使用Python实现在PDF中添加、导入、复制、移动与删除页面》在日常办公和自动化任务中,我们经常需要对PDF文件进行页面级的编辑,使用Python,你可以轻松实现这些操作,而无需依赖AdobeAc... 目录1. 向 PDF 添加空白页2. 从另一个 PDF 导入页面3. 删除 PDF 中的页面4. 在

C#借助Spire.XLS for .NET实现Excel工作表自动化样式设置

《C#借助Spire.XLSfor.NET实现Excel工作表自动化样式设置》作为C#开发者,我们经常需要处理Excel文件,本文将深入探讨如何利用C#代码,借助强大的Spire.XLSfor.N... 目录为什么需要自动化工作表样式使用 Spire.XLS for .NET 实现工作表整体样式设置样式配置

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题

《Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题》在爬虫工程里,“HTTPS”是绕不开的话题,HTTPS为传输加密提供保护,同时也给爬虫带来证书校验、... 目录一、核心问题与优先级检查(先问三件事)二、基础示例:requests 与证书处理三、高并发选型:

C#自动化实现检测并删除PDF文件中的空白页面

《C#自动化实现检测并删除PDF文件中的空白页面》PDF文档在日常工作和生活中扮演着重要的角色,本文将深入探讨如何使用C#编程语言,结合强大的PDF处理库,自动化地检测并删除PDF文件中的空白页面,感... 目录理解PDF空白页的定义与挑战引入Spire.PDF for .NET库核心实现:检测并删除空白页

C#利用Free Spire.XLS for .NET复制Excel工作表

《C#利用FreeSpire.XLSfor.NET复制Excel工作表》在日常的.NET开发中,我们经常需要操作Excel文件,本文将详细介绍C#如何使用FreeSpire.XLSfor.NET... 目录1. 环境准备2. 核心功能3. android示例代码3.1 在同一工作簿内复制工作表3.2 在不同

在.NET项目中嵌入Python代码的实践指南

《在.NET项目中嵌入Python代码的实践指南》在现代开发中,.NET与Python的协作需求日益增长,从机器学习模型集成到科学计算,从脚本自动化到数据分析,然而,传统的解决方案(如HTTPAPI或... 目录一、CSnakes vs python.NET:为何选择 CSnakes?二、环境准备:从 Py