您的位置:首页 > 理论基础 > 计算机网络

创建异步 HTTP 处理程序

2007-07-30 11:34 417 查看
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


C#


复制代码


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 处理程序

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

向 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 中映射扩展名

打开“Internet 服务管理器”。

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

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

选择“映射”选项卡。

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

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

测试自定义 HTTP 处理程序

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

测试自定义 HTTP 处理程序

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

请参见

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: