Wann sollte ich Async-Controller in ASP.NET MVC verwenden?

Wann sollte ich Async-Controller in ASP.NET MVC verwenden?

Vielleicht finden Sie meinen MSDN-Artikel zu diesem Thema hilfreich; Ich habe in diesem Artikel viel Platz eingenommen, um zu beschreiben, wann Sie sollten Verwenden Sie async auf ASP.NET, nicht nur wie um async zu verwenden auf ASP.NET.

Verstehe zuerst, dass async /await dreht sich alles um das Freigeben von Threads . Bei GUI-Anwendungen geht es hauptsächlich darum, den GUI-Thread freizugeben die Benutzererfahrung ist also besser. Bei Serveranwendungen (einschließlich ASP.NET MVC) geht es hauptsächlich darum, den Anforderungsthread freizugeben damit der Server skalieren kann.

Insbesondere nicht

  • Machen Sie Ihre individuellen Anfragen schneller fertig. Tatsächlich werden sie (nur ein winziges bisschen) langsamer abgeschlossen.
  • Kehren Sie zum Anrufer/Browser zurück, wenn Sie await drücken . await "gibt" nur an den ASP.NET-Threadpool ab, nicht an den Browser.

Ich würde sagen, es ist gut, es überall dort zu verwenden, wo Sie I/O machen. Es muss nicht unbedingt vorteilhaft sein , obwohl (siehe unten).

Allerdings ist es schlecht um es für CPU-gebundene Methoden zu verwenden. Manchmal denken Entwickler, dass sie die Vorteile von async nutzen können indem Sie einfach Task.Run aufrufen in ihren Controllern, und das ist eine schreckliche Idee. Da dieser Code den Anforderungs-Thread freigibt, indem er einen anderen Thread aufnimmt, gibt es überhaupt keinen Vorteil (und tatsächlich nehmen sie die Strafe für zusätzliche Thread-Wechsel auf sich)!

Sie können alle verfügbaren Methoden verwenden, die Ihnen zur Verfügung stehen. Im Moment unterstützen die meisten großen Player async , aber es gibt ein paar, die das nicht tun. Wenn Ihr ORM async nicht unterstützt , dann versuchen Sie nicht, es in Task.Run einzuschließen oder so ähnlich (siehe oben).

Beachten Sie, dass ich gesagt habe:"Sie könnten verwenden". Wenn Sie über ASP.NET MVC mit einem einzigen Datenbank-Back-End sprechen, dann werden Sie (fast sicher) keinen Skalierbarkeitsvorteil von async erhalten . Dies liegt daran, dass IIS weitaus mehr gleichzeitige Anforderungen verarbeiten kann als eine einzelne Instanz von SQL Server (oder anderen klassischen RDBMS). Wenn Ihr Back-End jedoch moderner ist – ein SQL Server-Cluster, Azure SQL, NoSQL usw. – und Ihr Back-End skalieren kann und Ihr Skalierbarkeitsengpass IIS ist, dann Sie können einen Skalierbarkeitsvorteil von async erhalten .

So viele Sie möchten. Beachten Sie jedoch, dass viele ORMs eine One-Operation-per-Connection-Regel haben. Insbesondere lässt EF nur einen einzigen Vorgang pro DbContext zu; dies gilt unabhängig davon, ob die Operation synchron oder asynchron ist.

Denken Sie auch wieder an die Skalierbarkeit Ihres Backends. Wenn Sie es mit einer einzelnen Instanz von SQL Server zu tun haben und Ihr IIS bereits in der Lage ist, SQL Server voll auszulasten, hilft Ihnen eine Verdoppelung oder Verdreifachung des Drucks auf SQL Server überhaupt nicht.


Asynchrone Aktion Methoden sind nützlich, wenn eine Aktion mehrere unabhängige lang andauernde Operationen ausführen muss.

Sollen meine Datenbankaufrufe asynchron sein?

Der IIS-Threadpool kann häufig viel mehr gleichzeitige Blockierungsanforderungen verarbeiten als ein Datenbankserver. Wenn die Datenbank der Engpass ist, beschleunigen asynchrone Aufrufe die Datenbankantwort nicht. Ohne einen Drosselungsmechanismus verlagert das effiziente Verteilen von mehr Arbeit an einen überlasteten Datenbankserver durch Verwendung asynchroner Aufrufe lediglich mehr Last auf die Datenbank. Wenn Ihre DB der Engpass ist, sind asynchrone Aufrufe kein Wundermittel.

Sie sollten siehe 1 und 2 Referenzen

Abgeleitet von @PanagiotisKanavos-Kommentaren:


Wie beim Programmieren üblich, kommt es darauf an . Es gibt immer einen Kompromiss, wenn man einen bestimmten Weg einschlägt.

async-await glänzt an Orten, an denen Sie wissen, dass Sie gleichzeitig Anfragen an Ihren Dienst erhalten, und Sie in der Lage sein möchten, aufzuskalieren Gut. Wie funktioniert async-await Hilfe bei der Skalierung? In der Tatsache, dass beim Aufrufen eines asynchronen IO-Aufrufs synchron , wie z. B. ein Netzwerkaufruf oder ein Zugriff auf Ihre Datenbank, wird der aktuelle Thread, der für die Ausführung verantwortlich ist, blockiert und wartet darauf, dass die Anforderung beendet wird. Wenn Sie async-await verwenden aktivieren Sie das Framework, um eine Zustandsmaschine für Sie zu erstellen, die sicherstellt, dass Ihre Methode nach Abschluss des IO-Aufrufs dort weiter ausgeführt wird, wo sie aufgehört hat.

Zu beachten ist, dass diese Zustandsmaschine einen subtilen Overhead hat. Wenn Sie eine Methode asynchron machen, wird sie nicht schneller ausgeführt , und das ist ein wichtiger zu verstehender Faktor und ein Missverständnis, das viele Menschen haben.

Eine weitere Sache, die bei der Verwendung von async-await zu berücksichtigen ist ist die Tatsache, dass es durchgehend asynchron ist , was bedeutet, dass Sie sehen, wie Async Ihre gesamte Aufrufliste von oben nach unten durchdringt. Das bedeutet, dass Sie, wenn Sie synchrone APIs verfügbar machen möchten, oft feststellen müssen, dass Sie eine bestimmte Menge an Code duplizieren, da Asynchronität und Synchronisierung nicht sehr gut zusammenpassen.

Wenn Sie sich dafür entscheiden, asynchrone IO-Aufrufe zu verwenden, dann ja, async-await eine gute Wahl, da immer mehr moderne Datenbankanbieter asynchrone Methoden anbieten, die das TAP (Task Asynchronous Pattern) implementieren.

So viele Sie wollen, solange Sie die Regeln Ihres Datenbankanbieters befolgen. Die Anzahl der asynchronen Aufrufe, die Sie tätigen können, ist unbegrenzt. Wenn Sie Abfragen haben, die unabhängig voneinander sind und gleichzeitig durchgeführt werden können, können Sie für jede eine neue Aufgabe erstellen und await Task.WhenAll verwenden warten, bis beide abgeschlossen sind.