在asp.net项目中,添加一个【一般处理程序】来处理请求是很自然的事,这样会得到一个实现自IHttpHandler的类,然后只需在ProcessRequest方法中写上处理逻辑就行了。但是这样的一个请求处理程序(下称ashx)是同步的,就是接待该次请求的线程会一直等待处理完才能解脱,后果就是,如果这个ashx比较耗时,并且同时对它的请求又多的话,服务器需要开启若干个线程来跑这个ashx,并且这些线程都要各自跑很久才能被收回或挪作它用,如果这样的ashx还有不少的话,那么对整个服务器资源的开销是很大的,所以有必要采用IHttpAsyncHandler来实现这种ashx,即异步请求处理程序,异步化以后,线程把请求接进来就完事了,反手就可以去处理其它请求,然后由别的线程硬件来处理具体的任务~取决于任务是CPU消耗型(密集运算,如图片处理)还是I/O型(数据库读写、网络访问等),老实说如果耗时任务总是CPU消耗型,那同步异步在资源消耗上没什么区别,因为总得有个线程来跑任务,换不换线程意义不大。但总的来说异步化没坏处,而且万一对任务类型评估错误呢。

改用IHttpAsyncHandler后,多了两个方法BeginProcessRequest和EndProcessRequest,原有的ProcessRequest事实上已经废弃,请求不会进入里面,而是改为在BeginProcessRequest中处理请求,原IsReusable属性功能不变。说回BeginProcessRequest,这是一个典型的传统异步方法(相对于.net 4.5后的async/await新式异步方法来说),逻辑相比原来的同步方法ProcessRequest有点绕,首先入参除了熟悉的HttpContext外还有两个,然后还有个IAsyncResult类型的返回值。熟悉APM(异步编程模型)套路的朋友知道该怎么搞,不熟悉的可参看MSDN,要点就是实例化一个实现IAsyncResult的类,在其中异步或起线程执行逻辑,然后返回这个对象。现成的实现IAsyncResult的类在.net 4.0后有Task,但如果项目不到4.0,你还找不到一个可以拿来就用的类,如果要为每个ashx实现一个IAsyncResult,想想都蛋疼,哪怕总共只需实现一个IAsyncResult我都不情愿,好在委托这个东西编译器会为它自动生成异步模型,于是有了下面这个简单的封装:

/// <summary>
/// 异步请求处理基类
/// <para>- 子类实现ProcessRequest方法并在其中处理请求</para>
/// <para>- 默认允许实例重用(IsReusable=true),子类可重写为false</para>
/// </summary>
public abstract class HttpAsyncHandler : IHttpAsyncHandler
{
readonly Action<HttpContext> _processRequestDel; protected HttpAsyncHandler() => _processRequestDel = ProcessRequest; /// <summary>
/// 处理请求
/// </summary>
//总是要有个让子类处理业务逻辑的地方,既然原来的ProcessRequest已废弃,不如废物利用
public abstract void ProcessRequest(HttpContext context); /// <summary>
/// 多次请求是否可以重用实例。默认true
/// </summary>
public virtual bool IsReusable => true; public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) =>
_processRequestDel.BeginInvoke(context, cb, extraData); //利用ProcessRequest委托的异步能力 //虽然不End也不会导致异步还没跑完就返回响应(HttpApplication的实现似乎保证这一点),但异步中抛出的异常会被忽略,所以需要End暴露问题
public void EndProcessRequest(IAsyncResult result) => _processRequestDel.EndInvoke(result);
}

有了这个封装好的基类,在写新的ashx时就可以把IHttpHandler改为HttpAsyncHandler,完了把ProcessRequest方法标成override就行,老ashx也可以经过简单修改异步化。举例:

public class FooHandler : HttpAsyncHandler // 替掉IHttpHandler
{
//加上override
public override void ProcessRequest(HttpContext context)
{
//在这里写逻辑
context.Response.Write("OK");
}
}

需要注意的是IsReusable在HttpAsyncHandler中已改为true,所以如果你的ashx明确需要false,请override该属性,如:

public override bool IsReusable => false;

对于.net 4.5及以上版本,微软已经写好了个HttpTaskAsyncHandler,性质一样,只不过形式上符合新式的async/await用法,总之目的都是让开发者可以优雅的使用异步ashx,不必繁琐的从IHttpAsyncHandler开始。

EOF

【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装的更多相关文章

  1. 普通B/S架构模式同步请求与AJAX异步请求区别(个人理解)

    在上次面试的时候有被问到过AJAX同步与异步之间的概念问题,之前没有涉及到异步与同步的知识,所以特意脑补了一下,不是很全面... 同步请求流程:提交请求(POST/GET表单相似的提交操作)---服务 ...

  2. 同步请求和异步请求的区别(理解ajax用)

    同步请求:发送方发送数据包后,等待接收方发回响应之后,才能发送下一个数据包的通信方式. 异步请求:发送方发送数据包后,不用等待接收方发回响应,就可以发送下一个数据包的通信方式. 同步通信:要求通信双方 ...

  3. SpringBoot异步请求

    何为异步请求 在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理.如果一个请求需要进行IO操作,比如 ...

  4. SpringBoot | 第二十章:异步开发之异步请求

    前言 关于web开发的相关知识点,后续有补充时再开续写了.比如webService服务.发邮件等,这些一般上觉得不完全属于web开发方面的,而且目前webService作为一个接口来提供服务的机会应该 ...

  5. tornado异步请求的理解(转)

    tornado异步请求的理解 http://www.kankanews.com/ICkengine/archives/88953.shtml 官网第一段话: Tornado is a Python w ...

  6. 同步请求和异步请求的区别,ajax异步请求如何理解

    同步请求和异步请求的区别 先解释一下同步和异步的概念 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式. 异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的 ...

  7. 深入理解Servlet3.0异步请求

    异步请求的基础概念 异步请求最直接的用法就是处理耗时业务,Http协议是单向的,只能客户端拉不能服务器主推. 异步请求的核心原理主要分为两大类:1.轮询.2长连接 轮询:就是定时获取返回结果. 长连接 ...

  8. ASP.NET之自定义异步HTTP处理程序(图文教程)

    前面我们学习了关于关于自定义同步HTTP处理程序,相信大家可能感觉有所成就,但是这种同步的机制只能对付客户访问较少的情况或者数据处理量不大的情况,而今天这篇文章就是解决同步HTTP处理程序的这个致命缺 ...

  9. JavaScript处理异步请求的几种方式(取异步函数返回值)

    JavaScript处理异步的几种方式 Javascript语言的执行环境是"单线程"(single thread,就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个 ...

随机推荐

  1. LeetCode之“链表”:Sort List

    题目链接 题目要求: Sort a linked list in O(n log n) time using constant space complexity. 满足O(n log n)时间复杂度的 ...

  2. Lucene 学习资料

    个机制的结合.关于中文的语言分析算法,大家可以在Google查关键词"wordsegment search"能找到更多相关的资料. 安装和使用 下载:http://jakarta. ...

  3. django-debug-tools 使用

    用django开发很快也很容易,但是很多时候我们的经验并不是很足,就会给自己挖下很多坑,不管是性能问题,还是开发语言使用技巧问题都会给应用的稳定带来危害, 开发之后的调试和调优就显得很重要,今天就尝试 ...

  4. vs 2010调用matlab dll显示窗口核心代码

    matlab代码: figure('NumberTitle','off','menubar','none','toolbar','none','name','Topo Image'); x=0:pi/ ...

  5. partition List(划分链表)

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  6. JVM(HotSpot) 7种垃圾收集器的特点及使用场景

    这里讨论的收集器基于JDK1.7Update 14之后的HotSpot虚拟机,这个虚拟机包含的所有收集器如下图3-5所示: 上图展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们 ...

  7. oracle超出打开游标的最大数的原因和解决方案

    oracle超出打开游标的最大数的原因和解决方案 分类: Oracle相关2012-06-05 10:36 6362人阅读 评论(0) 收藏 举报 oracle数据库sqljavasessionsys ...

  8. Day2_and_Day3 文件操作

    文件修改操作: 文件的修改操作:文件并没有修改操作,实际是将一个编写的新文件覆盖了原有的文件 替换文件中的某个内容: with open('old.txt','r',encoding='utf-8') ...

  9. javaWeb安全漏洞修复总结

    1 Web安全介绍1 2 SQL注入.盲注1 2.1 SQL注入.盲注概述 1 2.2 安全风险及原因 2 2.3 AppScan扫描建议 2 2.4 应用程序解决方案 4 3 会话标识未更新7 3. ...

  10. jsoup 使用总结1--添加header

    jsoup 使用总结1--添加header 大部分时候,我们使用jsoup解析网页的是否都是直接Jsoup.connect(url); 孰不知,我们可以添加header,例如 Host, Refere ...