你应该知道的 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

相关文章

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>

编程应该用 Mac 还是 PC ?

『有人的地方,就有江湖』—徐克。笑傲江湖。     序     一个竞争的市场,就会有对立的产生,这世界存在著很多不同的领域,领域好比是个江湖的缩影,因此就有许多门派的纷争,例如说浏览器领域有著最大宗的IE派,门派成长速度飞快,武功版号跳的跟台湾物价指数一样快的Chrome门,不断被模仿,一直被超越的Opera派;韧性极强,一直对抗几大势力的Firefox派等等,程序语言也有自己的领域

Weex入门教程之3,使用 Vue 开发 Weex 页面

环境安装 在这里简略地介绍下,详细看官方教程 Node.js 环境 Node.js官网 通常,安装了 Node.js 环境,npm 包管理工具也随之安装了。因此,直接使用 npm 来安装 weex-toolkit。 npm 是一个 JavaScript 包管理工具,它可以让开发者轻松共享和重用代码。Weex 很多依赖来自社区,同样,Weex 也将很多工具发布到社区方便开发者使用。

AsyncTask 异步任务解析

1:构建AsyncTask 子类的回调方法: A:doInBackground:   必须重写,所有的耗时操作都在这个里面进行; B: onPreExecute:     用户操作数据前的调用; 例如:显示一个进度条 等 ; C: onPostExecute:    当doInBackground 执行完成后;会自动把数据传给onPostExecute方法;也就是说:这个方法是处理返回的数据的方法