zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

NetASP教程异步HTTP 自定义 图文 处理程序
2023-06-13 09:14:43 时间

一、前言

1.对读者想说的话:(可跳过)

PS:MSDN从头到尾都是文字且文字很统一,恐怕很多人都感觉畏惧,懒的去看,所以我将其重要的部分提取出来,使用易懂的例子和简洁的语言来叙述。当然其中也免不了错误,希望各位亲们可以指出。

2.正式的开始

前面我们学习了关于关于自定义同步HTTP处理程序,相信大家可能感觉有所成就(大牛们可能会觉得soeasy)。但是这种同步的机制只能对付客户访问较少的情况或者数据处理量不大的情况(每次申请一个同步HTTP处理程序都会新建一个新的线程来处理,当申请量很大时,线程将会被堵塞,致使服务器性能低下,甚至宕机)。而今天这篇文章就是解决同步HTTP处理程序的这个致命缺点,有效的使用服务器的资源。

PS:异步(仅限在本文章下的情况):简单来说就是一部分操作在使用我们自己创建的线程,另一部分操作由操作系统调用自身的线程有条不紊的处理,这样我们可以将简单的处理由我们自身的线程完成,而复杂的处理则交给系统管理的线程来处理。因为这些线程是系统管理的所以不会出现卡死的情况,系统内部会自动的管理。当然系统会通过通知的方式告知我们的自己的线程该处理已经完成,这样我们就可以避免使用多线程技术,却难于管理的问题。

以下为图例:

二、注册与绑定(虽然前一篇已经讲述过,但是在这里仍然重新再讲一次)

为什么要有这两部呢?而且还是要注册与绑定这两个呢?

答案是你只写一个类vs是不可能知道你这个东西是干什么的,所以我们需要在web.config中注册我们自定义的HTTP处理程序。而绑定则是让iis知道我们这个站点中含有一个自定义的HTTP处理程序。(下面我将以iis7为例说明如何绑定)

1.注册

复制代码代码如下:

<configuration>
<system.web>
<httpHandlers>
<addverb="*"path="<!--这里写需要绑定的客户端申请的页面(*.smm,*.ffs,web1.ffe)-->"type="<!--这里写处理程序的类名-->"
</httpHandlers>
</system.web>
</configuration>
以上需要自行编写的部分我都已使用注释写好

2.绑定(iis7)

1)打开iis7-》打开 网站 节点-》点击你的网站的名称

2)双击

3)点击

4)

5)最后点击确定这样在iis中的绑定就完成了(后面的完整例子我将会以文字介绍该过程)

三、关于类的实现

这里我们将要实现两个接口的功能,下面我将分开来阐述

1.IHttpAsyncHandler接口

需实现方法以及属性如下:

   IAsyncResultBeginProcessRequest(HttpContextcontext,AsyncCallbackcb,Objectextradata) 
   启动对HTTP处理程序的异步调用
   参数说明:
            context:该对象提供对用于向HTTP请求提供服务的内部服务器对象(如RequestResponseSessionServer)的引用。
                    cb:当异步操作完成后调用该委托告知我们操作已经完成
                    extradata:处理该请求所需的所有额外数据
  返回值:
                   返回有关进程状态的IAsyncResult(可以让我们时刻查看异步调用中的当前状态)

 voidEndProcessRequest(IAsyncResultresult)
 进程结束时提供异步处理End方法


  参数说明:
                          result:有关进程状态的IAsyncResult(这里的result跟BeginProcessRequest返回的是同一个对象,只是内部的属性等等改变了)

注:但是我们还要实现不在IHttpAsyncHandler接口中的一个属性和一个方法,否则IIS会报错

boolIsRusable
表明是否使用池,只需要实现get,返回false表示不使用,返回true表示使用。

  voidProceessRequest(HttpContextcontext)
同步HTTP处理程序被调用的方法(这里并不会调用该方法,但是必须实现)



 2.IAsyncResutl接口

需实现方法以及属性如下:

   ObjectAsyncState
  获取用户定义的对象(其实就是以上的extradata并且只要实现get)

  WaitHandlerAsyncWaitHandle
  获取用于等待异步操作完成的WaitHandle(一般都是返回NULL并且只要实现get)  boolCompletedSynchronously
  获取异步操作是否同步完成的指示(一般都是返回false)  boolIsCompleted
  获取异步操作是否已完成的指示

 四、实现该功能(iis7/asp.net4.0/vs2010/windows764bit)

注:1.新建空web项目,并添加App_Code文件夹,并部署在iis上

    2.在App_Code中新建一个类,命名为"AsyncRequestHandler.cs"(这里的命名不影响,但是类名是关键)

    3.在AsyncRequestHandler.cs中引用"System.Threading"命名空间

下面我们将一步一步的学习实现这个功能,虽然只是一个很简单的例子,但是可以让你在以后的开发中更加灵活的运用。

1.实现IHttpAsyncHandler接口
代码如下:

复制代码代码如下:
publicclassAsyncHttpHandler:IHttpAsyncHandler
{
publicAsyncHttpHandler()
{
//
//TODO:在此处添加构造函数逻辑
//
}

publicboolIsReusable
{
get
{
returnfalse;//表明不使用池
}
}

publicvoidProcessRequest(HttpContextcontext)//不调用必须实现的方法
{
thrownewInvalidOperationException();
}

///<summary>
///当客户申请时执行的异步处理
///</summary>
///<paramname="context">包含httpresponse、httprequest、server对象</param>
///<paramname="cb">回调函数</param>
///<paramname="extradata">需要传递的参数</param>
///<returns>返回有关进程的状态信息</returns>
publicIAsyncResultBeginProcessRequest(HttpContextcontext,AsyncCallbackcb,objectextradata)//必须实现的方法
{
context.Response.Write("<p>AsyncHttpHandler</p>");//向页面中写入html表明是该信息来自何处
AsyncOperationop=newAsyncOperation(context,cb,extradata);//实例化实现了IAsyncResult接口的类(主要实现异步处理的类)
op.StartAsyncWork();//开始异步处理
returnop;//返回该对象
}

///<summary>
///当BeginProcessRequest中的returnop;与异步的处理完成后调用(调用完既呈现页面)
///</summary>
///<paramname="result">为op,但是属性已改变</param>
publicvoidEndProcessRequest(IAsyncResultresult)
{
}
}

2.实现IAsyncResult接口(与上面的代码在同一个文件中)
代码如下:
复制代码代码如下:
publicclassAsyncOperation:IAsyncResult
{
HttpContext_context;//保存context的引用
AsyncCallback_cb;//保存回调委托的引用
object_state;//保存额外的信息
bool_iscomplate;//保存异步操作是否完成

///<summary>
///构造函数,将AsyncHttpHandler的参数全部传递进来
///</summary>
///<paramname="context"></param>
///<paramname="cb"></param>//该回调不可被重写,否则将会出现客户端永久等待的状态
///<paramname="state"></param>//构造时该值可以传递任意自己需要的数据
publicAsyncOperation(HttpContextcontext,AsyncCallbackcb,objectstate)
{
_context=context;
_cb=cb;
_state=state;
_iscomplate=false;//表明当前异步操作未完成
}

///<summary>
///实现获得当前异步处理的状态
///</summary>
boolIAsyncResult.IsCompleted
{
get
{
return_iscomplate;
}
}

///<summary>
///返回false即可
///</summary>
boolIAsyncResult.CompletedSynchronously
{
get
{
returnfalse;
}
}

///<summary>
///将返回额外的信息
///</summary>
objectIAsyncResult.AsyncState
{
get
{
return_state;
}
}

///<summary>
///为空
///</summary>
WaitHandleIAsyncResult.AsyncWaitHandle
{
get
{
returnnull;
}
}

///<summary>
///表明开始异步处理的主函数(方法名可以改,但上面的调用也需要一起改)
///</summary>
publicvoidStartAsyncWork()
{
ThreadPool.QueueUserWorkItem(newWaitCallback(StartAsyncTask),null);//相信很多玩国.netwinform开发的一定认识
}

///<summary>
///异步操作调用的方法
///</summary>
///<paramname="workstate">为QueueUserWorkItem方法中第二个参数传递的值</param>
publicvoidStartAsyncTask(objectworkstate)
{
_context.Response.Write("<p>CompletionIsThreadPoolThreadis"+Thread.CurrentThread.IsThreadPoolThread+"</p>");
_iscomplate=true;//表明异步操作已完成
_cb(this);//调用回调函数表明完成
}
}

3.web.config配置

内容如下(红色方框部分为需要添加的内容):

4.iis绑定(如何绑定见二)

5.测试

时你随意的写 test.async或者 asd.async等等,最后呈现的页面都是一致的。这样就达到我们的效果了

五、看完这些只是浅层

这里我想指明的是看完这些并不代表你已经掌握了所有,因为关于异步还有一个部分就是共享资源的使用,这个就需要使用到WaitHandle类,否则就会导致多个线程同时访问并修改同一个共享资源,后果可想而知。所以在这篇文章完结的同时也意味着新的问题的开始,所以我们要不断的学习下去。