Async-Controller in ASP.NET MVC: Echte Vorteile / Wie erreicht?


12

Ich habe einen Artikel über asynchrone Controller-Methoden in ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx ) durchgearbeitet und denke Ich kann den Punkt verfehlen.

Betrachten Sie diese Methode, die ich geschrieben habe und die einem Beispiel aus dem Artikel sehr ähnlich ist:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

So wie ich die Dinge verstehe, werden sich die Dinge zur Laufzeit folgendermaßen entwickeln:

  1. Für eine eingehende HTTP-Anforderung wird ein ASP.NET-Thread erstellt.

  2. Dieser Thread wird (nachdem er vermutlich einige notwendige Vorarbeiten durchgeführt hat) in meine Index () -Methode oben eingegeben.

  3. Die Ausführung erreicht das Schlüsselwort "await" und startet einen Datenerfassungsprozess in einem anderen Thread.

  4. Der ursprüngliche "ASP.NET" -Thread kehrt zu dem Code zurück, der meine Handlermethode aufgerufen hat, mit einer Instanz der Klasse Task als Rückgabewert.

  5. Der Infrastrukturcode, der meine Handler-Methode aufgerufen hat, wird weiterhin auf dem ursprünglichen "ASP.NET" -Thread ausgeführt, bis er einen Punkt erreicht, an dem das eigentliche ActionResult-Objekt verwendet werden muss (z. B. zum Rendern der Seite).

  6. Der Aufrufer greift dann mit dem Task.Result-Member auf dieses Objekt zu, wodurch es (dh der "ASP.NET" -Thread) auf den in Schritt 3 implizit erstellten Thread wartet.

Ich sehe nicht, was dies im Vergleich zu derselben Sache ohne Warten / Asynchronisieren bewirkt, abgesehen von zwei Dingen, die ich als unbedeutend empfinde:

  • Der Aufruferthread und der von await erstellte Arbeitsthread können einige Zeit parallel arbeiten (der "bis" -Teil von # 5 oben). Meine Vermutung ist, dass der Zeitraum ziemlich klein ist. Wenn die Infrastruktur eine Controller-Methode aufruft, benötigt sie meiner Meinung nach im Allgemeinen das eigentliche ActionResult des Controller-Aufrufs, bevor sie viel (wenn überhaupt) mehr kann.

  • Es gibt einige hilfreiche neue Infrastrukturen, die sich auf das Timeout und das Abbrechen lang laufender asynchroner Controller-Vorgänge beziehen.

Der Zweck des Hinzufügens von asynchronen Controller-Methoden besteht angeblich darin, diese ASP.NET-Arbeitsthreads freizugeben, um tatsächlich HTTP-Anforderungen zu beantworten. Diese Threads sind eine endliche Ressource. Leider sehe ich nicht, wie das im Artikel vorgeschlagene Muster tatsächlich dazu dient, diese Threads zu erhalten. Und selbst wenn dies der Fall ist und die Last der Bearbeitung der Anforderung auf einen Nicht-ASP.NET-Thread verlagert, was bringt das? Unterscheiden sich Threads, die eine HTTP-Anforderung verarbeiten können, stark von Threads im Allgemeinen?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Nicht unbedingt. asyncbenötigt keinen weiteren Thread ... Es ist eine Fortsetzung. Dies kann erreicht werden, indem Anweisungen für denselben Thread neu angeordnet werden.
Robert Harvey


"Die Ausführung erreicht das Schlüsselwort" await "und startet einen Datenerfassungsprozess in einem anderen Thread." Du hast das rückwärts verstanden: Das Warten ist, wenn es zurückkommt. Versuchen Sie, es aufzuteilen, damit Sie das Ergebnis von GetAllAsync () in einer Variablen speichern und stattdessen darauf warten und prüfen, ob es klarer wird.
Esben Skov Pedersen

Antworten:


9

ASP.Net, das die Task Parallel Library (TPL) nicht verwendet, ist in der Anzahl der Anforderungen, die gleichzeitig verarbeitet werden können, durch die Anzahl der Threads in einem Thread-Pool begrenzt. ASP.Net, das die TPL verwendet, wird durch die CPU / den Speicher / die E / A der Maschinenbehandlungsanforderungen begrenzt.

Die Task Parallel Library (TPL) verbraucht keine Threads so, wie Sie es zu glauben scheinen. Aufgaben sind keine Threads, sondern ein Wrapper um eine Recheneinheit. Der Taskplaner ist für die Ausführung jeder Aufgabe in einem Thread verantwortlich, der nicht ausgelastet ist. Zur Laufzeit blockiert das Warten auf eine Aufgabe den Thread nicht, sondern parkt lediglich den Ausführungsstatus, damit er zu einem späteren Zeitpunkt fortgesetzt werden kann.

Normalerweise wird eine einzelne HTTP-Anforderung von einem einzelnen Thread verarbeitet, wodurch dieser Thread vollständig aus dem Pool entfernt wird, bis eine Antwort zurückgegeben wird. Mit der TPL sind Sie nicht an diese Einschränkung gebunden. Jede eingehende Anforderung startet eine Fortsetzung mit jeder Recheneinheit, die erforderlich ist, um eine Antwort zu berechnen, die auf einem beliebigen Thread im Pool ausgeführt werden kann. Mit diesem Modell können Sie viel mehr gleichzeitige Anforderungen verarbeiten als mit Standard-ASP.Net.


Wann wird der ASP.NET-Thread an den Pool zurückgegeben? Wann wird das Schlüsselwort "Warten" getroffen?
user1172763

Mit async / await + TPL kann der Compiler Ihren Code in unabhängige Recheneinheiten aufteilen, die vom Taskplaner ausgeführt werden. Ein Thread wird konzeptionell an den Pool zurückgegeben, wenn der Taskplaner keine weiteren Aufgaben mehr ausführen kann und der Thread die ihm übertragene Arbeit beendet.
Mortalapeman

Dies ist konzeptionell korrekt und wahrscheinlich eine nützliche Antwort. Die Realität ist jedoch aufgrund der Agilität des Threads etwas komplizierter .
John Wu
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.