Dieser Artikel wurde maschinell übersetzt.

Innovationen

Erneute Betrachtung asynchroner ASP.NET-Seiten

Dino Esposito

Synchrone und asynchrone HTTP-Handler hat ASP.NET immer unterstützt werden. Nun, wurde ASP.NET 2.0 neue Features zu erleichtern und schnellere für Entwickler zum Erstellen von asynchroner Seiten. Insbesondere für serverbasierte Anwendungen sind asynchrone Vorgänge von grundlegender Bedeutung für die Aktivierung der Skalierbarkeit. Wenn Sie feststellen, müssen Sie die vorhandene Webanwendung skalieren, wird der erste Aspekt zu berücksichtigen wie viel Asynchrony zu den Seiten hinzugefügt werden können.

In dieser Hinsicht Verhalten ASP.NET wie jede andere Serveranwendung, die einige Hintergrund für mehrere Clients arbeitet. Ein Thread im Besitz mit ASP.NET wird jede eingehende Anforderung zugewiesen, die aus dem Threadpool von ASP.NET abgeholt wird. Der Thread ist blockiert, bis der Vorgang beendet wurde und einige Antwort für den Client generiert wurde. Wie lange soll der Thread warten? Die Laufzeitumgebung ASP.NET kann so konfiguriert werden, definieren Sie einen benutzerdefinierten Timeout (90 Sekunden ist die Standardeinstellung), aber es ist wichtiger, um zu verhindern, dass den Thread blockiert.

Wenn Sie mit potenziell langwierigen Vorgängen arbeiten, das Timeout sichergestellt höchstens nur, dass nach einer bestimmten Anzahl von Sekunden, der Thread freigegeben und in den Pool zurückgegeben zu werden. Stattdessen ist erwünscht um zu verhindern, dass den Thread für längere Zeit blockiert. Idealerweise sollten Sie den Thread auf eine Anforderung zu beginnen und dann zu einigen anderen ASP.NET-fremde Thread ergeben. Im gleichen Thread oder einen anderen Namen aus dem Pool ASP.NET werden erneut nach Abschluss des Vorgangs herausgesucht die Antwort an den Client senden. Dieses Paradigma wird als asynchrone ASP.NET-Seiten bezeichnet.

Wenn es sich um asynchrone Vorgänge geht, sollten Sie zwischen Seiten, die asynchron in Bezug auf die Benutzer sind und Seiten, die in Bezug auf die ASP.NET-Laufzeit asynchron sind unterscheiden. In Bezug auf den Benutzer asynchrone Seiten ist der nur geeignete Ansatz eine AJAX-Operation. Mit AJAX zu einer möglicherweise langsamen Vorgang verringert die Auswirkungen auf den Endbenutzer jedoch keine Erleichterung der 
ASP.NET-Laufzeit bringen.

Asynchrone Seiten und die Laufzeit von ASP.NET

Je länger der Thread nicht auf die Anforderung reagiert, längere einen Thread aus dem Pool ASP.NET, neue eingehende Anforderungen zu bedienen subtrahiert wird. Wenn keine Threads verfügbar, um neue Anforderungen zu bedienen sind, werden die Anforderungen in eine Warteschlange eingereiht. Dies kann zu Verzögerungen und Beeinträchtigung der Gesamtleistung führen.

In ASP.NET sind HTTP-Handler synchron in der Standardeinstellung. Mit asynchronen HTTP-Handlern müssen explizit konzipiert und durch die Anwendung leicht unterschiedlicher Schnittstellen implementiert werden. Ein synchroner Handler unterscheidet sich von einem asynchronen Handler in einem wichtigen Aspekt: anstatt die synchrone ProcessRequest-Methode verwendet ein asynchroner Handler die unten aufgeführten Methoden sind Teil der IHttpAsyncHandler-Schnittstelle:

IAsyncResult BeginProcessRequest(

     HttpContext context, 

     AsyncCallback cb, 

     object extraData);


void EndProcessRequest(
     

     IAsyncResult result);

BeginProcessRequest enthält den Vorgang ausgeführt werden, um die Anforderung zu bedienen. Dieser Code sollte so ausgelegt sein, zum Starten des Vorgangs auf einem sekundären Thread und kehrt sofort zurück. EndProcessRequest enthält den Code die Anforderung nicht abschließen, die bereits gestartet wurde.

Wie Sie sehen können, wird eine asynchrone HTTP-Anforderung in zwei Teile teilen – vor und nach dem Punkt “ Async ” – den Punkt im Lebenszyklus Anforderung, in dem der Thread, der die Anforderung besitzt ändert. Bei der asynchronen Punkt erreicht ist, ergibt der ursprünglichen ASP.NET-Thread Steuerelement mit einem anderen Thread. Diese möglicherweise langwierigen Vorgang erfolgt zwischen den beiden Teilen die ASP.NET-Anforderung. Jeder Teil der asynchronen Anforderung ausgeführt wird, unabhängig von der andere ohne Affinität des Threads Bezug ist. Anders gesagt, besteht keine Garantie dafür, dass derselbe Thread die beiden Teile der Anforderung erledigt wird. Der Effekt ist, dass keine Threads für die Dauer des Vorgangs blockiert werden.

Zu diesem Zeitpunkt ist die offensichtliche Frage: Welche Threads kümmert wirklich “ langwierige ” Vorgang? E/a-Komplettierungsports wird von ASP.NET intern verwendet, um die Beendigung einer Anforderung zu verfolgen. Bei der asynchronen Punkt erreicht ist, kann ASP.NET die ausstehende Anforderung an einen e/a-Abschlussanschluss gebunden und registriert einen Rückruf an eine Benachrichtigung zu erhalten, wenn die Anforderung beendet wurde. Das Betriebssystem wird eine eigene dedizierte Threads verwenden, um die Beendigung der Operation zu überwachen, wodurch der ASP.NET-Thread davor, warten Sie, im Leerlauf vollständig freigegeben. Wenn der Vorgang beendet wird, setzt das Betriebssystem eine Meldung in der Warteschlange Abschluss, die wodurch den Rückruf für die ASP.NET ausgelöst werden, der dann eine eigene Threads abholt die Anforderung fortsetzen. Wie bereits erwähnt, werden e/a-Komplettierungsports ein Feature des BETRIEBSSYSTEMS.

Die Real Natur der asynchrone Seiten

In ASP.NET sind asynchrone Seiten i. d. r. das Konzept der Verbesserung der Leistung einer bestimmten Seite verantwortlich für das Durchführen eines möglicherweise langwierigen Vorgangs zugeordnet. Jedoch sollten einige weitere Punkte beachtet werden. Aus Sicht des Benutzers sich synchrone und asynchrone Anforderungen annähernd gleich aussehen. Wenn der angeforderte Vorgang erwartet wird, z. B. 30 Sekunden dauern, wird der Benutzer mindestens 30 Sekunden warten, um die neue Seite zu wechseln. Dies geschieht unabhängig von der synchrone oder asynchrone Implementierung der Seite. Darüber hinaus überraschen Sie nicht zu Wenn etwas mehr Zeit zum Abschließen einer Anforderung eine asynchronen Seite endet. Was ist der Vorteil von asynchronen Seiten?

Skalierbarkeit ist nicht ganz dasselbe wie Leistung. Oder zumindest Skalierbarkeit ist, über die Leistung jedoch auf einer anderen Ebene – die gesamte Anwendung anstelle einer einzelnen Anforderung. Der Vorteil, den asynchrone Seiten in der Tabelle zu bringen ist wesentlich weniger Arbeit für die Threads im Pool für ASP.NET. Dies nicht lange Anforderungen schneller ausgeführt, aber das System nicht lange Anforderungen wie gewohnt zu bedienen ist es hilfreich, d. h. mit keine speziellen Verzögerungen entstehen laufende langsame Anforderungen.

Asynchrone Anforderungen nutzen asynchrone HTTP-Handler, die immer eine Funktion in die ASP.NET-Plattform wurden. Von ASP.NET Web Forms und ASP.NET MVC bieten jedoch Ihre eigenen Einrichtungen vereinfacht Entwicklern das Implementieren von asynchronen Aktionen vornehmen. Im weiteren Verlauf dieses Artikels werden asynchrone Operationen in ASP.NET MVC 2 erläutert.

Asynchrone Controller-Aktionen

In ASP.NET MVC 1.0 kann jeder Domänencontroller Aktion nur synchron ausgeführt. Die MVC Futures-Bibliothek wurde jedoch eine neue AsyncController-Klasse hinzugefügt. Nach einem experimentellen Zeitraum Async-API für Domänencontroller wurde das ASP.NET MVC Framework offiziell hinzugefügt, und es vollständig zur Verfügung und Version 2 von ASP.NET MVC Framework dokumentiert ist. (Die Syntax und in diesem Artikel erläuterten Features beziehen sich auf ASP.NET MVC 2 RC.)  Wenn Sie etwas mit der AsyncController-Klasse in der MVC Futures-Bibliothek wiedergeben, werden Sie einige Änderungen feststellen und die API ist einfacher und sauberer.

Der Zweck der AsyncController besteht darin, sicherzustellen, dass alle Aktion verfügbar gemachten Methoden asynchron, Ausführen ohne den allgemeinen Ansatz zur Programmierung, die das ASP.NET MVC Framework charakterisiert. Das Diagramm im Abbildung 1 zeigt die Abfolge der Schritte hinter der Verarbeitung einer asynchronen Aktion.

Figure 1 Mechanics of an Async Action Method in ASP.NET MVC
Abbildung 1 Funktionsweise von einer asynchronen Vorgang-Methode in ASP.NET MVC

Der asynchronen Punkt wird zwischen der Ausführung und Ereignisse ausgeführt. Wenn die Aktion-Invoker teilt mit, dass Sie über die zum Ausführen der Aktion des Threads beschäftigt ist weiterhin der ursprünglichen ASP.NET-Thread, der die Anforderung aus der Web-Server-Warteschlange entnommen. Zu diesem Zeitpunkt wird die Aktion ausgeführt. Am Ende Wenn der Aktion-Invoker benachrichtigen, das Ereignis Aktion ausgeführt werden kann ist möglicherweise ein anderes ASP.NET-Thread dauert der Anforderung sorgt. Abbildung 2 zeigt dieses Szenario.


Abbildung 2 Thread für eine asynchrone Aktion Methodenaufruf wechseln

Bevor die Details beim Erstellen und Debuggen von asynchrone Methoden besprochen, sollte eine andere grundlegender Punkt der asynchronen Vorgänge an ASP.NET klare vorgenommen: nicht alle Aktionen sind gute Kandidaten für asynchrone Operationen zu.

Die Real Ziel von asynchronen Vorgängen

Nur e/A-gebundener Operationen sind gute Kandidaten für zunehmend Async Aktion Methoden für eine asynchrone Controllerklasse. Ein e/A-gebundenen Vorgang ist ein Vorgang, der die lokale CPU für die Vervollständigung abhängen, nicht. Wenn ein e/A-gebundenen Vorgang aktiv ist, wartet die CPU nur Daten verarbeitet werden (die gedownloadet werden,) von externen Speicher (eine Datenbank oder einem remote-Dienst). E/A-gebundener Operationen sind im Gegensatz zur CPU-gebundene Vorgänge, die die CPU-Aktivität hängt die Durchführung einer Aufgabe.

Ein typisches Beispiel für einen e/A-gebundenen Vorgang handelt es sich um den Aufruf einer remote-Dienst. In diesem Fall die Aktion-Methoden ausgelöst, die Anforderung und dann einfach Antwort zu warten gedownloadet werden. Die eigentliche Arbeit wird remote von einem anderen Computer und einer anderen CPU durchgeführt wird. Folglich wird der ASP.NET-Thread hängen, warten und Leerlauf. Freigibt, von der Abgabe der anderen eingehenden Anforderungen bedienen wartenden Leerlaufthread der Leistungsgewinn erzielen Sie mit der asynchronen Implementierung von Aktionen oder Seiten.

Wie sich herausstellt, dass nicht alle langwierige Operationen einen konkreten Vorteil Ihnen Wenn asynchron implementiert. Eine längere Berechnung im Speicher profitieren nicht wesentlich von asynchronen Implementierung. Er konnte auch etwas langsamer ausgeführt werden, weil die gleiche CPU sowohl für die ASP.NET-Anforderung als auch für die Berechnung eingesetzt werden. Darüber hinaus müssen Sie möglicherweise immer noch einen ASP.NET-Thread physisch von der Berechnung kümmern. Ggf. bei der Verwendung der asynchronen Implementierung für die CPU-gebundene Vorgänge ist wenig nutzen. Andererseits, wenn Remoteressourcen beteiligt sind, können sogar mehrere 
resources, mithilfe asynchroner Methoden tatsächlich die Leistung der Anwendung, falls dies nicht die Leistung der einzelnen Anforderung steigern Sie.

Ich werde an dieser Stelle kurz mit einem Beispiel zurück. Im Moment konzentrieren let’s über die Syntax zum Definieren und Ausführen von asynchronen Aktivitäten in ASP.NET MVC benötigt.

Erkennen von Async-Routen

In der Möglichkeit, eine asynchrone Route, die sich von einer synchronen Route besteht? In MVC Futures wurden Sie aufgefordert, verschiedene Methoden verwenden, um synchrone und asynchrone Routen zu registrieren. Hier wird die alte Möglichkeit, eine asynchrone Route zu registrieren:

routes.MapAsyncRoute(

    "Default",

    "{controller}/{action}/{id}",

    new { controller = "Home", action = "Index", id = "" }

);

Sie mussten die MapAsyncRoute-Erweiterungsmethode anstelle des standardmäßigen MapRoute Sie klassische synchronen Methoden eingesetzt haben würde. In ASP.NET MVC 2 RC jedoch wurde diese Unterscheidung entfernt. Nun einfach eine Möglichkeit, Ihre Routen zu registrieren – die MapRoute-Methode – unabhängig davon, wie die Aktion dann ausgeführt werden.

Der URL der Anforderung wird daher wie gewohnt verarbeitet und der Name der Controllerklasse verwenden herausgefunden. Es ist erforderlich, in der Tat, dass eine Async-Methode für eine Controllerklasse definiert ist, die von der neuen AsyncController-Klasse, die hier dargestellten abgeleitet wird:

public class TestController : AsyncController

{

  ...

}

Wenn die Controllerklasse AsyncController erbt, lautet die Konvention für die Zuordnung von Namen Aktion zu Methoden etwas anders. Eine AsyncController-Klasse kann synchrone und asynchrone Anforderungen bedienen. Die Konvention verwendet kann als Ergebnis sowohl eine Methode ausführen und eine Methode RunAsync, erkennen, wie hier gezeigt:

public class TestController : AsyncController

{

  public ActionResult Run(int id) 

  {

     ...

  }

  public void RunAsync(int id) 

  {

     ...

  }

}

Wenn Sie dies tun, wird jedoch eine Ausnahme ausgelöst werden (siehe Abbildung 3).

Ein Async-Aktion wird nach Namen identifiziert, und das erwartete Muster ist XxxAsync, wobei Xxx der Standardname des Aktion auszuführende angibt. Natürlich ist Wenn Sie eine andere Methode mit dem Namen Xxx vorhanden ist und es ist nicht disambiguated unter Verwendung von Attributen, dann wie in AusnahmeAbbildung 3.


Abbildung 3 Mehrdeutige Verweise in der Name der Aktion

Das Wort Async wird ein Suffix betrachtet. Der URL zum Aufrufen der RunAsync-Methode wird nur das Präfix ausführen enthalten. Der folgende URL wird z. B. die RunAsync, übergeben einen Wert von 5 als Parameter Route-Methode aufrufen:

http://myserver/demo/run/5

Ob dies aufgelöst wird, wie eine synchrone oder asynchrone Aktion hängt von den Methoden haben Sie in der AsyncController-Klasse. Die XxxAsync-Methode, gibt jedoch nur den Trigger des Vorgangs. Der Finalizer der Anforderung ist eine andere Methode in die Controllerklasse, die mit dem Namen XxxCompleted:

public ActionResult RunCompleted(DataContainer data)

{

    ...

}

Beachten Sie die andere Signatur der beiden Methoden definieren die Async-Aktion. Der Trigger wird erwartet, einem void-Methode. Wenn Sie einen beliebigen Wert wieder definieren, wird der Rückgabewert einfach ignoriert. Die Eingabeparameter der Methode XxxAsync werden unterliegen Modell binden wie gewohnt. Die Finalizer-Methode gibt ein ActionResult-Objekt wie gewohnt, und erhält ein benutzerdefiniertes Objekt, das die Daten enthält, die zum Verarbeiten und übergeben Sie in das Ansichtsobjekt erwartet hat. Ein spezielles Protokoll ist erforderlich, damit die Werte berechnet, indem Sie den Trigger zu den Parametern, die von der Finalizer deklariert.

Der AsyncController-Klasse

Die AsyncController-Controller-Klasse erbt von Domänencontroller und eine Reihe von neuen Schnittstellen implementiert, wie hier gezeigt:

public abstract class AsyncController : Controller, 

                IAsyncManagerContainer, 

IAsyncController, IController

Der am häufigsten unterschiedliche Rufsignale Aspekt ein Async-Controller ist das besondere Aktion Invoker-Objekt, das hinter den Kulissen eingesetzt wird, um Operationen. Die Invoker-Anforderungen, die ein Leistungsindikator, um die Anzahl einzelner Arbeitsgänge verfolgen, die die Aktion und die synchronisiert werden muss, bevor die allgemeine Aktion deklariert werden kann, wurde beendet. Abbildung 4 stellt eine Beispielimplementierung für eine asynchrone Aktion.

Abbildung 4 Eine einfache asynchrone Aktion-Methode

public void RunAsync(int id) 

{

    AsyncManager.OutstandingOperations.Increment();



    var d = new DataContainer();

     ...

            

    // Do some remote work (i.e., invoking a service)

     ...



    // Terminate operations

    AsyncManager.Parameters["data"] = d;

    AsyncManager.OutstandingOperations.Decrement();

}

public ActionResult RunCompleted(DataContainer data)

{

   ...

}

Der OutstandingOperations-Member für die AsyncManager-Klasse stellt einen Container, der die Anzahl ausstehender asynchroner Operationen verwaltet. Es ist eine Instanz der OperationCounter-Hilfsklasse und stellt eine ad-hoc-API zum Inkrementieren und Dekrementieren. Die Inkrement-Methode ist nicht auf unären Schritten beschränkt, wie hier gezeigt:

AsyncManager.OutstandingOperations.Increment(2);

service1.GetData(...);

AsyncManager.OutstandingOperations.Decrement();

service2.GetData(...);

AsyncManager.OutstandingOperations.Decrement();

Das AsyncManager-Parameter-Wörterbuch wird Gruppe Werte verwendet, um die Finalizer-Methode der asynchrone Aufruf als Argumente übergeben werden. Parameter-Wörterbuch wird erwartet, dass der Eintrag für jeden Parameter an den Finalizer übergeben werden, in dem früheren Beispiel für die XxxCompleted-Methode. Wenn eine Übereinstimmung zwischen Einträgen in das Wörterbuch und Parameter nicht gefunden werden kann, wird ein Standardwert für den Parameter angenommen – null für Verweistypen. Es wird keine Ausnahme ausgelöst, wenn versucht wird, ein null-Objekt zuzugreifen. Die XxxCompleted-Methode empfängt Parameter eines beliebigen unterstützten Typs und verwendet diese zum ViewData-Sammlung oder ein starker Typbindung Objekt erkannt wird, indem Sie die Ansicht zu füllen. Die XxxCompleted-Methode ist dafür verantwortlich, ein ActionResult-Objekt zurückzugeben.

Anpassen ein gut oder nicht?

Nachbereiten von, synchrone Anforderungen sind eine erforderliche Funktion in ASP.NET und in der Tat haben asynchrone HTTP-Handler seit ASP.NET 1.0 unterstützt wurde.

ASP.NET Web Forms und ASP.NET MVC bieten Tools, mit denen Code asynchronen Operationen, die jeweils in eigenen Anwendungsmodell auf höherer Ebene – in ASP.NET MVC Sie asynchrone Domänencontroller haben und in Web Forms Sie asynchrone Seiten abhängig. 

Der Schlüsselaspekt der Async-Aktionen ist jedoch entscheiden, ob eine bestimmte Aufgabe eine gute Übereinstimmung für eine asynchrone Implementierung ist. Async-Methoden sollten nur um e/A-gebundener Operationen erstellt werden. Und schließlich Bedenken Sie, dass asynchrone Methoden werden nicht ausgeführt schneller selbst, jedoch können andere Anforderungen schneller ausgeführt.

Dino Esposito ist der Autor der bevorstehenden Microsoft Press-Reihe "Programming ASP.NET MVC" und war auch an "Microsoft .NET: Architecting Applications for the Enterprise" (Microsoft Press, 2008) beteiligt. Esposito lebt in Italien und ist ein weltweit gefragter Referent bei Branchenveranstaltungen. Sie finden seinen Blog unter weblogs.asp.net/despos.

Dank an den folgenden technischen Experten für die Überprüfung dieses Artikels Stefan Schackow