HttpApplication中的异步线程
一、Asp.net中的线程池设置
在Asp.net的服务处理中,每当服务器收到一个请求,HttpRuntime将从HttpApplication池中获取一个HttpApplication对象处理此请求,请求的处理过程将被排入线程池中,对于Asp.net来说,在Machine.config文件的processModel部分中可以设置线程池中的参数。
Asp.net线程相关的参数配置:
参数 | 配置 |
autoConfig | 基于服务器的配置自动设置。 |
maxWorkerThreads | 设置每个CPU的最大工作线程数量,可以设置为5~100,默认为20,建议设置为100 |
minWorkerThreads | 设置每个CPU的最少工作线程数量,默认为1 |
maxIoThreads | 配置每个CPU的最大I/O线程数量,可以设置的范围为5~100,默认为20,建议设置为100 |
minIoThreads | 配置每个CPU最少工作线程数量,默认为1 |
HttpRuntime元素的配置参数:
参数 | 配置 |
minFreeThreads | 处理新请求保留的最少自由线程数量,默认值为8.建议每CPU设置为88个。这些最小空闲线程用于避免没有线程可用而造成死锁。因此,当线程池的线程小于这个数,请求就被排入队列,而不会使用这些线程处理。 |
minLocalRequestFreeThreads | 为本地主机请求保留的最少自由线程数量,默认值为4.建议每CPU设置为76个。同上(只是针对本地请求) |
appRequestQueueLimit | 在Asp.net没有足够的线程来处理请求的时候,将会把这些请求排入一个请求队列中等待处理,该项用来设置这个队列的长度,当队列长度超过这个参数将返回503、默认为5000。 |
优化的第一原则是:对于每一个请求尽可能使用一个线程完成处理。
二、异步步骤中的异步点
在HttpApplication的处理过程中,为了提高线程的利用率,对于一个请求尽可能只使用一个线程完成处理。
由于Asp.net处理采用管道的处理模式,必须保证处理步骤的逻辑顺序。所以,有些处理必须在后继的处理之前完成,所以,除非此时真的需要多个可以并行的计算密集任务,否则,启动多个线程并不能提高网站的处理速度。
对于HttpApplication处理管道中每一个事件的处理步骤,有同步与异步两个方式处理:
- 同步:提供一个事件处理方法直接完成处理步骤;
- 异步:一个用于启动涉及I/O的处理步骤,一个用于I/O完成之后的处理步骤;
对于一个需要等待的处理步骤,我们可以分出一个异步点,在这个异步点之前启动耗时的操作,然后直接结束当前的线程,在没有线程参与的情况下,进行这个耗时的输入输出任务(耗时但不需要线程参与的阶段,就称异步点),在任务完成之后,重新从线程池获取一个线程来继续当前请求的处理。
如同步的BeginRequest对应的异步处理方式定义如下:
public void AddOnBeginRequestAsync(BeginEventHandler bh, EndEventHandler eh)
其中BeginEventHandler用于启动处理的委托,EndEventHandler用于处理完成任务之后的委托。
对于HttpApplication管道的处理来说,这些事件使用的同步方式的委托类型都是EventHandler类型,这个委托类型的定义如下:
public delegate void EventHandler(Object sender, EventArgs e)
对于异步方式的处理,则使用相应的两个委托完成,一个用于启动的委托BeginEventHandler,一个用于结束的委托EndEventHandler。结束操作的委托将工作在一个线程池提供的线程之上。
在异步方式下,处理管道将不再连续使用一个线程完成,而是每个处理步骤都可能在一个线程上进行,所以,我们不能假定处理管道总是处于一个线程,而使用基于线程的特征。
三、启动和完成异步步骤
在Asp.net中,启动与完成异步步骤的对象分别如下:
- 启动异步步骤的委托类型为System.Web.BeginEventHandler。
- 完成异步步骤的委托类型为System.Web.EndEventHandler。
其委托的定义如下:
public delegate IAsyncResult BeginEventHandler(Object sender,EventArgs e,AsyncCallback cb,Object extraData)
public delegate void EndEventHandler(IAsyncResult ar)
可以看到,实际上与AsyncCallback委托的类型是完全一样的。
其中AsyncCallback类型定义了完成处理之后调用方法的类型,这个类型定义如下:
public delegate void AsyncCallback(IAsyncResult ar)
而extraData则定义了可以传递到AsyncCallback方法的一个自定义的参数对象。
四、异步处理程序
对于同步的处理程序,通过接口IHttpHandler中定义的方法ProcessRequest进行处理。这个方法的定义如下:
void ProcessRequest(HttpContext context)
对于异步的处理程序,这个方法也同样被两个方法所代替,这就是定义在异步处理程序接口IHttpAsyncHandler中的两个方法
- BeginProcessRequest;
- EndProcessRequests;
如果一个处理程序实现了异步的接口,那么HttpApplication将使用异步方法来调用这个处理程序。
1、异步处理程序接口
异步的处理程序接口定义在命名空间System.Web下:
public interface IHttpAsyncHandler : IHttpHandler
{
IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
void EndProcessRequest(IAsyncResult result); bool IsReusable { get; }
void ProcessRequest(HttpContext context);
}
2、在处理程序中异步调用Web服务
对于一个典型的Web服务来说,我们需要在BeginProcessRequest方法的最后调用启动调用Web服务的方法,然后这个方法就可以结束了。
系统随后在没有线程参与的情况下进行漫长的Web服务调用,当服务调用完成之后,Asp.net将会把EndProcessRequest排入线程池的I/O线程队列中。最后,EndProcessRequest将被调用。在这个方法中,我们通过调用结束Web服务的方法来获取服务返回的数据。
五、异步页面
页面Page是Asp.net网站开发中最常用到的页面生成技术,从本质上将,它也是一个处理程序。从Page类的目的来说,它主要用来生成HTML的特殊处理程序。
这个处理程序默认情况下实现了IHttpHandler接口,所以,可以看成一个同步的处理程序。如果我们需要实现异步的页面处理程序,并不需要手工修改它所实现的接口,而是通过页面指令Async来指定。当设置为true的时候,表示生成的页面类将实现接口IHttpAsyncHandler。这样,这个页面对象将通过异步方法被访问。
<%@ Page Async="true" %>
在这种情况下,页面处理的过程将被分成两个部分:从开始到包括PreRender处理部分由IHttpAsyncHandler接口中的BeginProcessRequest方法处理;从PreRenderComplete到处理结束将由EndProcessRequest方法处理。在PreRender和PreRenderComplete之间就是异步页面的异步点。这个过程用来等待长时间异步操作的完成。
1、页面异步任务的启动和完成
页面对象的AddOnPreRenderCompleteAsync方法用来注册异步操作的两个方法,这两个方法将在异步点之前和异步点之后被调用。
这两个委托就是:
- BeginEventHandler;
- EndEventHandler;
2、异步页面任务
在Asp.net 2.0以后,可以通过PageAsyncTask在页面的处理中注册多个异步操作,每一个操作通过PageAsyncTask定义。
public sealed class PageAsyncTask
使用这个类的时候,页面的异步状态可以设置为true,也可以设置为false。当设置为false的时候,页面的处理线程将被阻塞,所以,在使用异步页面任务的时候,应该将页面设置为异步状态。
通过类的构造函数,我们定义异步任务的开始处理方法、完成处理方法,甚至还可以提供一个超时的处理方法。最复杂的一个构造函数如下所示:
public PageAsyncTask(
BeginEventHandler beginHandler,
EndEventHandler endHandler,
EndEventHandler timeoutHandler,
Object state,
bool executeInParallel
)
页面对象的RegisterAsyncTack(PageAsyncTask task)可以注册异步任务:
public void RegisterAsyncTask(
PageAsyncTask task
)
3、异步页面中访问Web服务的三种方式
暂时跳过
HttpApplication中的异步线程的更多相关文章
- Android中使用异步线程更新UI视图的几种方法
在Android中子线程是不能更新ui的. 所以我们要通过其他方式来动态改变ui视图, 1.runOnUiThreadactivity提供的一个轻量级更新ui的方法,在Fragment需要使用的时候要 ...
- Erlang运行时中的无锁队列及其在异步线程中的应用
本文首先介绍 Erlang 运行时中需要使用无锁队列的场合,然后介绍无锁队列的基本原理及会遇到的问题,接下来介绍 Erlang 运行时中如何通过“线程进度”机制解决无锁队列的问题,并介绍 Erlang ...
- 卸载AppDomain动态调用DLL异步线程执行失败
应用场景 动态调用DLL中的类,执行类的方法实现业务插件功能 使用Assembly 来实现 但是会出现逻辑线程数异常的问题 使用AppDomain 实现动态调用,并卸载. 发现问题某个插件中开启异步线 ...
- SpringBoot使用异步线程池实现生产环境批量数据推送
前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...
- C#中的线程一(委托中的异步)
C#中的线程一(委托中的异步) 一.同步委托 我们平时所用的委托以同步居多,我们编写一个方法和相关委托进行演示: publicdelegatevoid DoSomethingDelegate(stri ...
- 关于GCD同步组实现多个异步线程的同步执行中的注意点
在App开发中经常会遇到多个线程同时向服务器取数据, 如果每个线程取得数据后都去刷新UI会造成界面的闪烁 也有可能出现部分数据还没有获取完毕造成程序crash 之前在网上看到很多是利用dispatch ...
- Eclipse RCP中超长任务单线程,异步线程处理
转自:http://www.blogjava.net/mydearvivian/articles/246028.html 在RCP程序中,常碰到某个线程执行时间比较很长的情况,若处理不好,用户体验度是 ...
- Android中使用Thread线程与AsyncTask异步任务的区别
最近和几个朋友交流Android开发中的网络下载问题时,谈到了用Thread开启下载线程时会产生的Bug,其实直接用子线程开启下载任务的确是很Low的做法,那么原因究竟如何,而比较高大上的做法是怎样? ...
- springboot 中如何正确在异步线程中使用request
起因: 有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题. 示例代码: @GetMapping("/getParams&q ...
随机推荐
- 全局函数的Result一定要每次都初始化,否则上次的结果会被保持到下一次继续使用
测试半天,原来是因为这个原因.下面例子中,Result:=''必须写,否则其结果会被累计,真是昏倒!! function MyPaths(tache: IXMLTaskType) : String; ...
- 【转】GCC4.6编译的warning -Werror
原文网址:http://blog.sina.com.cn/s/blog_605f5b4f0101bct7.html New warnings for unused variables and para ...
- 认识什么是SEO
何为SEO? SEO是由英 文Search Engine Optimization缩写而来, 中文意译为“搜索引擎优化”,是指在了解搜索引擎自然排名机制的基础上,对网站进行内部及外部的调整优化,改进网 ...
- TCP快速重传和快速恢复
当tcp传送一个分组时会设置一个定时器,如果在规定的实际间隔内没有收到ACK分组,那么则重新传输该分组,但是 如果tcp收到三个连续的ACK分组,此时不管是否过超时间隔则重传该分组,具体步骤如下: 1 ...
- [bzoj1003][ZJOI2006][物流运输] (最短路+dp)
Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...
- 禁用UITableViewCell 重用机制
有时候不想让Cell重用,怎么办勒.接下来介绍两种方法 方法一 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAt ...
- jQuery插件Jeditable的使用(Struts2处理)
Jeditable - Edit In Place Plugin For jQuery,是一款JQuery就地编辑插件.也就是在页面直接点击需要编辑的内容,就会自动变成文本框进行编辑.它的官方 ...
- "git rm" 和 "rm" 的区别
"git rm" 和 "rm" 的区别 FEB 3RD, 2013 | COMMENTS 这是一个比较肤浅的问题,但对于 git 初学者来说,还是有必要提一下的 ...
- vue-router 快速入门
ue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用.vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来.传统的页面应用 ...
- Flashback Recovery Area的设置与取消
在Oracle 10g中, Flash back家族分为以下成员: Flashback Database, Flashback Drop,Flashback Query(分Flashback Quer ...