在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. eclipse 设置maven来自动下载源码与doc

    通常我们通过maven来使用各种库文件,想要真正了解别人的类实现方法,需要查看别人的源码,maven给我们提供了这个便利,它不仅可以下载各种库文件,还会下载对应的源码和doc文档. 一.在工具栏找到W ...

  2. LIRe 源代码分析 7:算法类[以颜色布局为例]

    ===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...

  3. x265 (HEVC编码器,基于x264) 介绍

    x265要出来了.简单翻译了一下项目网站首页的介绍. x265是一个开源项目,是一个将视频编码为h.265/高效率的视频编码(HEVC)格式的免费的库,在GNU GPL条款下发布.它的源代码是免费提供 ...

  4. iOS评分功能、APP中打开其他应用程序

    1.评分功能 iOS中评分支持功能开发非常简单. NSString *str = [NSString stringWithFormat: @"itms-apps://itunes.apple ...

  5. 《HelloGitHub》第 25 期

    <HelloGitHub>第 25 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程. ...

  6. 春天的事务之9.3编程式事务 - 跟我学spring3

    9.3编程式事务 9.3.1编程式事务概述 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理. Spring框架提供一致的事务抽象,因此对于JDBC还是JTA事务都是采用相同 ...

  7. java原子操作

    一.何谓Atomic? Atomic一词跟原子有点关系,后者曾被人认为是最小物质的单位.计算机中的Atomic是指不能分割成若干部分的意思.如果一段代码被认为是Atomic,则表示这段代码在执行过程中 ...

  8. 基于 HTML5 Canvas 的工控机柜 U 位动态管理

    前言 U 是一种表示服务器外部尺寸的单位,是 unit 的缩略语,详细的尺寸由作为业界团体的美国电子工业协会(EIA)所决定.之所以要规定服务器的尺寸,是为了使服务器保持适当的尺寸以便放在铁质或铝质的 ...

  9. css 字体两端对齐

    我想作为一个前端工作者,总会遇到这样的场景,一个表单展示的字段标题有4个字也有2个字的时候,这样子同时存在想展示的美观一点,就需要字体两端对齐了,其实实现方式很简单,我针对其中一种来做下介绍,以后方法 ...

  10. Entity Framework分页扩展

    Entity Framework分页在我初入门时总是困扰这我,无论是SQL分页还是Entity Framework的分页,总是显得那么麻烦,因此对于Entity Framework单独封装了分页. 一 ...