创建异步 HTTP 处理程序

ASP.NET
如何:创建异步 HTTP 处理程序

 

使用异步 HTTP 处理程序,您可以在启动一个外部进程(例如对远程服务器的方法调用)的同时继续该处理程序的处理工作,而不必等待外部进程的完成。在异步 HTTP 处理程序的处理期间,ASP.NET 将通常用于外部进程的线程放回线程池中,直到处理程序收到来自外部进程的回调。这样可以避免阻止线程,从而提高性能,因为一次只能执行有限数量的线程。如果许多用户都在请求依赖于外部进程的同步 HTTP 处理程序,那么操作系统可能很快就会用完所有线程,因为大量线程被阻止,正在等待外部进程。

下面的代码示例演示了一个异步 HTTP 处理程序,该处理程序在 ASP.NET 应用程序中处理对扩展名为 .SampleAsync 的文件的请求。该示例演示了处理程序的代码,然后演示如何将 .SampleAsync 扩展名映射到 ASP.NET 中的处理程序。最后,该示例演示如何在 IIS 中将 .SampleAsync 扩展名映射到 ASP.NET,以便 IIS 可以将以 .SampleAsync 结尾的请求转发给 ASP.NET。

有关 ASP.NET 运行库如何与 IIS 交互的更多信息,请参见 ASP.NET 应用程序生命周期概述

创建 HelloWorldAsyncHandler HTTP 处理程序类

  • 在 App_Code 目录中创建一个名为 HelloWorldAsyncHandler 的类,并向类文件中添加以下代码:

    Visual Basic
    Imports Microsoft.VisualBasic
    Imports System.Web
    Imports System.Threading
    
    Public Class HelloWorldAsyncHandler
        Implements IHttpAsyncHandler
    
        Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property
    
        Public Function BeginProcessRequest( _
            ByVal context As System.Web.HttpContext, _
            ByVal cb As System.AsyncCallback, _
            ByVal extraData As Object) _
            As System.IAsyncResult _
            Implements System.Web.IHttpAsyncHandler.BeginProcessRequest
            context.Response.Write("<p>Begin IsThreadPoolThread is " _
                & Thread.CurrentThread.IsThreadPoolThread & "</p>" & vbCrLf)
            Dim asynch As New AsynchOperation(cb, context, extraData)
            asynch.StartAsyncWork()
            Return asynch
        End Function
    
        Public Sub EndProcessRequest(ByVal result As _
             System.IAsyncResult) _
             Implements System.Web.IHttpAsyncHandler.EndProcessRequest
        End Sub
    
        Public Sub ProcessRequest(ByVal context _
                As System.Web.HttpContext) _
                Implements System.Web.IHttpHandler.ProcessRequest
            Throw New InvalidOperationException()
        End Sub
    End Class
    
    Class AsynchOperation
        Implements IAsyncResult
        Private _completed As Boolean
        Private _state As [Object]
        Private _callback As AsyncCallback
        Private _context As HttpContext
    
        ReadOnly Property IsCompleted() As Boolean _
                Implements IAsyncResult.IsCompleted
            Get
                Return _completed
            End Get
        End Property
    
        ReadOnly Property AsyncWaitHandle() As WaitHandle _
                Implements IAsyncResult.AsyncWaitHandle
            Get
                Return Nothing
            End Get
        End Property
    
        ReadOnly Property AsyncState() As [Object] _
                Implements IAsyncResult.AsyncState
            Get
                Return _state
            End Get
        End Property
    
        ReadOnly Property CompletedSynchronously() As Boolean _
                Implements IAsyncResult.CompletedSynchronously
            Get
                Return False
            End Get
        End Property
    
        Public Sub New(ByVal callback As AsyncCallback, _
                ByVal context As HttpContext, _
                ByVal state As [Object])
            _callback = callback
            _context = context
            _state = state
            _completed = False
        End Sub
    
        Public Sub StartAsyncWork()
            ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartAsyncTask), Nothing)
    
        End Sub
    
        Private Sub StartAsyncTask(ByVal workItemState As [Object])
            _context.Response.Write("<p>Completion IsThreadPoolThread is " & Thread.CurrentThread.IsThreadPoolThread & "</p>" & vbCrLf)
    
            _context.Response.Write("Hello World from Async Handler!")
            _completed = True
            _callback(Me)
    
        End Sub 'StartAsyncTask
    End Class 'AsynchOperation
    

     

    using System;
    using System.Web;
    using System.Threading;
    
    class HelloWorldAsyncHandler : IHttpAsyncHandler
    {
        public bool IsReusable { get { return false; } }
    
        public HelloWorldAsyncHandler()
        {
        }
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
        {
            context.Response.Write("<p>Begin IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "</p>/r/n");
            AsynchOperation asynch = new AsynchOperation(cb, context, extraData);
            asynch.StartAsyncWork();
            return asynch;
        }
    
        public void EndProcessRequest(IAsyncResult result)
        {
        }
    
        public void ProcessRequest(HttpContext context)
        {
            throw new InvalidOperationException();
        }
    }
    
    class AsynchOperation : IAsyncResult
    {
        private bool _completed;
        private Object _state;
        private AsyncCallback _callback;
        private HttpContext _context;
    
        bool IAsyncResult.IsCompleted { get { return _completed; } }
        WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }
        Object IAsyncResult.AsyncState { get { return _state; } }
        bool IAsyncResult.CompletedSynchronously { get { return false; } }
    
        public AsynchOperation(AsyncCallback callback, HttpContext context, Object state)
        {
            _callback = callback;
            _context = context;
            _state = state;
            _completed = false;
        }
    
        public void StartAsyncWork()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
        }
    
        private void StartAsyncTask(Object workItemState)
        {
    
            _context.Response.Write("<p>Completion IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "</p>/r/n");
    
            _context.Response.Write("Hello World from Async Handler!");
            _completed = true;
            _callback(this);
        }
    }
    

    该代码实现 BeginProcessRequest 方法。该方法向当前的 HttpContext 对象的 Response 属性中写入一个字符串,创建一个 AsyncOperation 类的新实例,然后调用 StartAsyncWork 方法。然后,StartAsyncWork 方法向 ThreadPool 对象添加 StartAsyncTask 委托。当有线程可用时,将调用 StartAsyncTask 方法,该方法向 Response 属性写出另外一个字符串,然后通过调用 AsyncCallback 委托完成该任务。

注册自定义 HTTP 处理程序

在创建了自定义 HTTP 处理程序类之后,必须在 Web.config 文件中注册该类,以便由 ASP.NET 来处理对带有 .SampleAsync 扩展名的文件的请求。

在 Web.config 文件中注册自定义 HTTP 处理程序

  1. 如果您的网站没有 Web.config 文件,请创建一个 Web.config 文件。

  2. 向 Web.config 文件添加下面的代码:

    <configuration>
      <system.web>
        <httpHandlers>
          <add verb="*" path="*.SampleAsync" 
            type="HelloWorldAsyncHandler"/>
        </httpHandlers>
      </system.web>
    </configuration>

    该代码将 HelloWorldAsyncHandler 处理程序注册为对以 .SampleAsync 结尾的请求的处理程序。

为 HTTP 处理程序扩展名配置 IIS

IIS 只将针对某些文件类型的请求传递给 ASP.NET 进行处理。默认情况下,具有 .aspx、.ascx、.asmx 等扩展名的文件已映射到 ASP.NET,但是,如果您希望由 ASP.NET 来处理您所定义的文件扩展名,则必须在 IIS 中注册这些扩展名。有关更多信息,请参见 ASP.NET 应用程序生命周期概述

在 IIS 中映射扩展名

  1. 打开“Internet 服务管理器”。

  2. 右击您的应用程序,然后选择“属性”。

  3. 在“目录”选项卡中,单击“配置”。

  4. 选择“映射”选项卡。

  5. 添加一个新的关联,将 .SampleAsync 映射到要使用的 Aspnet_isapi.dll 版本。

  6. 如果希望无论是否存在用户请求的文件名,该处理程序都将运行,请清除“检查文件是否存在”复选框。

测试自定义 HTTP 处理程序

在创建并注册自定义 HTTP 处理程序之后,就可以通过在应用程序中请求具有 .SampleAsync 扩展名的资源来测试该处理程序。

测试自定义 HTTP 处理程序

  • 浏览至您的应用程序,然后在浏览器中输入一个以 .SampleAsync 结尾的 URL。

请参见

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值