Gewusst wie: Erstellen eines asynchronen HTTP-Handlers
Aktualisiert: November 2007
In dieser exemplarischen Vorgehensweise wird das Erstellen eines asynchronen HTTP-Handlers veranschaulicht. Mit asynchronen HTTP-Handlern können Sie einen externen Prozess starten (z. B. einen Methodenaufruf auf einem Remoteserver), während der Handler weiterarbeitet. Der Handler kann fortfahren, ohne das Ende des externen Prozesses abwarten zu müssen.
Während der Verarbeitung eines asynchronen HTTP-Handlers platziert ASP.NET den Thread, der gewöhnlich für den externen Prozess verwendet würde, wieder im Threadpool, bis der Handler vom externen Prozess einen Rückruf erhält. Dadurch wird ein Blockieren von Threads verhindert und die Leistung verbessert, da nur eine begrenzte Anzahl von Threads gleichzeitig ausgeführt werden kann. Wenn viele Benutzer synchrone, von externen Prozessen abhängige HTTP-Handler anfordern, kann es schnell passieren, dass im Betriebssystem keine weiteren Threads verfügbar sind, da viele Threads blockiert sind und auf externe Prozesse warten.
Im Beispiel in dieser exemplarischen Vorgehensweise wird ein asynchroner HTTP-Handler veranschaulicht, der Anforderungen für Dateien mit der Dateinamenerweiterung .SampleAsync in einer ASP.NET-Anwendung verarbeitet. Im Beispiel wird der Code für den Handler gezeigt, und Sie erfahren, wie Sie dem Handler in ASP.NET die Erweiterung .SampleAsync zuordnen. In diesem Beispiel wird zudem veranschaulicht, wie Sie ASP.NET in IIS die Erweiterung .SampleAsync zuordnen, sodass Anfragen, die auf .SampleAsync enden, von IIS an ASP.NET weitergeleitet werden.
Weitere Informationen zur Interaktion zwischen der ASP.NET-Laufzeit und IIS 6.0 finden Sie unter Übersicht über den Lebenszyklus von ASP.NET-Anwendungen für IIS 5.0 und 6.0. Weitere Informationen zur Integration von ASP.NET in IIS 7.0 finden Sie unter Übersicht über den Lebenszyklus von ASP.NET-Anwendungen für IIS 7.0.
In dieser exemplarischen Vorgehensweise werden u. a. die folgenden Aufgaben veranschaulicht:
Erstellen von Code für eine HTTP-Handlerklasse. Die Klasse muss die ProcessRequest-Methode und die IsReusable-Eigenschaft implementieren.
Registrieren des Handlers in der Datei Web.config und Zuordnen der Dateinamenerweiterung .SampleAsync.
Zuordnen der Dateinamenerweiterung .sample zu ASP.NET in IIS.
Vorbereitungsmaßnahmen
Für die Durchführung dieser exemplarischen Vorgehensweise benötigen Sie Folgendes:
Visual Studio oder Visual Web Developer.
Eine ASP.NET-Website, die mit IIS ausgeführt werden kann.
IIS 6.0 oder IIS 7.0.
Erstellen einer asynchronen HTTP-Handlerklasse
Als Erstes erstellen Sie eine Klasse, die den asynchronen Handler implementiert.
So erstellen Sie eine HelloWorldAsyncHandler-HTTP-Handlerklasse
Wenn für die Webseite, mit der Sie arbeiten, noch kein Ordner App_Code vorhanden ist, erstellen Sie einen solchen im Stammverzeichnis der Site.
Erstellen Sie im Verzeichnis App_Code eine Klasse mit dem Namen HelloWorldAsyncHandler, und fügen Sie der Klassendatei folgenden Code hinzu:
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); } }
Im Code wird die BeginProcessRequest-Methode implementiert. Die Methode schreibt eine Zeichenfolge in die Response-Eigenschaft des aktuellen HttpContext-Objekts, erstellt eine neue Instanz der AsyncOperation-Klasse und ruft die StartAsyncWork-Methode auf. Die StartAsyncWork-Methode fügt dann dem ThreadPool-Objekt den StartAsyncTask-Delegaten hinzu. Sobald ein Thread verfügbar ist, wird die StartAsyncTask-Methode aufgerufen, die eine weitere Zeichenfolge in die Response-Eigenschaft schreibt. Anschließend wird die Aufgabe durch Aufrufen des AsyncCallback-Delegaten abgeschlossen.
Registrieren des benutzerdefinierten HTTP-Handlers in IIS 6.0
Nachdem Sie die benutzerdefinierte HTTP-Handlerklasse erstellt haben, müssen Sie sie in der Datei Web.config der Anwendung registrieren. Dadurch kann ASP.NET beim Empfangen von Anforderungen an Ressourcen, deren URL auf .SampleAsync endet, den Handler finden.
Für das Registrieren des Handlers gibt es unterschiedliche Methoden, je nachdem, ob Sie IIS 6.0 oder IIS 7.0 verwenden. In diesem Abschnitt wird beschrieben, wie ein Handler in IIS 6.0 registriert wird. Im nächsten Abschnitt wird beschrieben, wie ein Handler in IIS 7.0 registriert wird.
So registrieren Sie den Handler in IIS 6.0
Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.
Fügen Sie der Datei Web.config das folgende hervorgehobene Markup hinzu:
<configuration> <system.web> <httpHandlers> <add verb="*" path="*.SampleAsync" type="HelloWorldAsyncHandler"/> </httpHandlers> </system.web> </configuration>
Das Konfigurationselement registriert den HelloWorldAsyncHandler-Handler als Handler für Anforderungen mit der Endung .SampleAsync.
Registrieren Sie eine Zuordnung für Anwendungserweiterungen für die Dateinamenerweiterung .SampleAsync mithilfe von IIS-Manager. Weitere Informationen finden Sie unter Gewusst wie: Konfigurieren einer HTTP-Handlererweiterung in IIS.
Registrieren des benutzerdefinierten HTTP-Handlers in IIS 7.0
In IIS 7.0 kann eine Anwendung im klassischen oder im integrierten Modus ausgeführt werden. Im klassischen Modus werden Anforderungen annähernd auf die gleiche Weise verarbeitet wie in IIS 6.0. Im integrierten Modus werden Anforderungen von IIS 7.0 mithilfe einer Pipeline verwaltet, sodass Anforderungen, Module und andere Features für ASP.NET freigegeben werden können.
In IIS 7.0 muss der Handler zur Handlerregistrierung entweder in der Datei Web.config oder in IIS-Manager registriert werden. Da die Administration in IIS 7.0 zentralisiert wurde, werden Änderungen in der Datei Web.config der Anwendung in der IIS-Manager-Schnittstelle der Anwendung reflektiert und umgekehrt. In den folgenden Verfahren werden die Handler in der Datei Web.config registriert.
Für IIS 7.0 im klassischen Modus und im integrierten Modus gibt es verschiedene Verfahren für die Registrierung des Handlers. Führen Sie das Verfahren für den von Ihnen verwendeten IIS-Modus aus.
So registrieren Sie den Handler in IIS 7.0 im klassischen Modus
Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.
Fügen Sie der Datei Web.config das folgende markierte Element hinzu.
Hinweis: Ersetzen Sie den richtigen Pfad für die Datei aspnet_isapi.dll. Die DLL-Datei befindet sich in dem Ordner, in dem .NET Framework installiert ist. Standardmäßig ist dies C:\WINDOWS\Microsoft.NET\Framework\Version.
<configuration> <system.web> <httpHandlers> <add verb="*" path="*.SampleAsync" type="HelloWorldAsyncHandler"/> </httpHandlers> </system.web> <system.webServer> <handlers> <add verb="*" path="*.SampleAsync" name="HelloWorldAsyncHandler" type="HelloWorldAsyncHandler" modules="IsapiModule"/> scriptProcessor="%path%\aspnet_isapi.dll" </handlers> </system.webServer> </configuration>
Das Konfigurationselement registriert den benutzerdefinierten Handler nach dem Klassennamen und ordnet diesem Handler die Dateinamenerweiterung .SampleAsync zu.
Hinweis: Registrieren Sie den Handler sowohl im Abschnitt handlers als auch im Abschnitt httpHandlers, da Sie eine benutzerdefinierte Dateinamenerweiterung registrieren. Im klassischen Modus ist der Handler mithilfe des modules-Attributs als ISAPI-Modul angegeben, um die Abwärtskompatibilität zu gewährleisten. Der Pfad der ASP.NET-ISAPI-DLL wird durch das scriptProcessor-Attribut angegeben. Das name-Attribut ist im handlers-Abschnitt erforderlich.
So registrieren Sie den Handler in IIS 7.0 im integrierten Modus
Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.
Fügen Sie der Datei Web.config das folgende markierte Element hinzu.
<configuration> <system.webServer> <handlers> <add verb="*" path="*.SampleAsync" name="HelloWorldAsyncHandler" type="HelloWorldAsyncHandler"/> </handlers> </system.webServer> </configuration>
Das Konfigurationselement registriert den benutzerdefinierten Handler nach dem Klassennamen und ordnet diesem Handler die Dateinamenerweiterung .SampleAsync zu.
Hinweis: Die Registrierung befindet sich im Abschnitt handlers, jedoch nicht im Abschnitt httpHandlers. Das name-Attribut ist erforderlich.
Testen des benutzerdefinierten HTTP-Handlers
Nach dem Erstellen und Registrieren des benutzerdefinierten HTTP-Moduls können Sie dieses testen.
So testen Sie den benutzerdefinierten HTTP-Handler
Wechseln Sie zur Anwendung, und geben Sie im Browser eine URL mit der Endung .SampleAsync ein.
Der in der HelloWorldAsyncHandler-Klasse definierte Text wird angezeigt.
Siehe auch
Aufgaben
Exemplarische Vorgehensweise: Erstellen eines synchronen HTTP-Handlers
Konzepte
Übersicht über den Lebenszyklus von ASP.NET-Anwendungen für IIS 5.0 und 6.0