Share via


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

  1. Wenn für die Webseite, mit der Sie arbeiten, noch kein Ordner App_Code vorhanden ist, erstellen Sie einen solchen im Stammverzeichnis der Site.

  2. 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

  1. Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.

  2. 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.

  3. 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

  1. Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.

  2. 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

  1. Wenn für die Website noch keine Web.config-Datei vorhanden ist, erstellen Sie diese im Stammverzeichnis der Website.

  2. 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

Weitere Ressourcen

Einführung in HTTP-Handler