async TaskHttpResponseMessage Ruft VS HttpResponseMessage Get ab

7

Ich würde Ihre Hilfe im Folgenden brauchen. Seit fast einem Monat lese ich über Tasks und async.

Ich wollte versuchen, mein neu erworbenes Wissen in einem einfachen wep-api-Projekt umzusetzen. Ich habe die folgenden Methoden und beide funktionieren wie erwartet:

%Vor%

Also die Frage. Ich habe versucht, Fiedler zu benutzen und zu sehen, was der Unterschied zwischen diesen beiden ist. Der asynchrone ist etwas schneller, aber was ist der wirkliche Vorteil bei der Implementierung von etwas Ähnlichem in einer Web-API?

    
Veronica_Zotali 18.09.2014, 00:11
quelle

3 Antworten

21

Wie andere bereits erwähnt haben, besteht der Punkt von async in ASP.NET darin, dass einer der ASP.NET-Threadpool-Threads freigegeben wird. Das funktioniert hervorragend für natürlich-asynchrone Operationen wie E / A-gebundene Operationen, da dies ein Thread weniger auf dem Server ist (es gibt keinen Thread, der die asynchrone Operation "a href=" http: //blog.stephencleary "verarbeitet" .com / 2013/11 / there-is-no-thread.html "> wie ich es auf meinem Blog erkläre ). Daher ist der primäre Vorteil von async auf der Serverseite Skalierbarkeit .

Sie möchten jedoch Task.Run (und, noch schlimmer, Task.Factory.StartNew ) auf ASP.NET vermeiden. Ich nenne dies "falsche Asynchronität", weil sie nur synchrone / blockierende Arbeit an einem Thread-Pool-Thread ausführen. Sie sind in UI-Apps nützlich, in denen Sie die Arbeit vom UI-Thread abschieben möchten, damit die Benutzeroberfläche reaktionsfähig bleibt. Sie sollten jedoch (fast) nie in ASP.NET oder anderen Server-Apps verwendet werden.

Durch die Verwendung von Task.Run oder Task.Factory.StartNew auf ASP.NET wird die Skalierbarkeit verringert. Sie werden einige unnötige Thread-Schalter verursachen. Bei länger andauernden Vorgängen könnten Sie die ASP.NET-Thread-Pool-Heuristik beenden, wodurch zusätzliche Threads erstellt und später unnötigerweise zerstört werden. Ich lese diese Leistungsprobleme Schritt für Schritt in einem anderen Blog-Beitrag nach .

Sie müssen also darüber nachdenken, was jede Aktion tut und ob asynchron sein soll. Wenn dies der Fall ist, sollte diese Aktion asynchron sein. In Ihrem Fall:

%Vor%

Was genau macht Request.CreateResponse ? Es wird nur ein Antwortobjekt erstellt. Das war's - nur eine schicke new . Es gibt keine I / O, und es ist sicherlich nicht etwas, das zu einem Hintergrund-Thread weggeschoben werden muss.

Allerdings ist GetUsers viel interessanter. Das klingt eher wie ein Datenlesen, das ist I / O-basiert. Wenn Ihr Backend skalieren kann (z. B. Azure SQL / Tables / etc), sollten Sie zuerst async vornehmen und sobald Ihr Service eine GetUsersAsync anzeigt, könnte diese Aktion async too: werden / p> %Vor%     

Stephen Cleary 18.09.2014 01:26
quelle
2

Es macht mehr Sinn, wo der Anruf bei wichtigen IO-Operationen stattfindet. Ja, Async ist schneller, da es den Anforderungsthread für die Zeit freigibt, in der die Operationen ausgeführt werden. Aus Sicht des Web-Servers geben Sie daher dem Pool einen Thread zurück, der vom Server für zukünftige Anrufe verwendet werden kann.

Also für z.B. Wenn Sie eine Suchoperation auf dem SQL-Server ausführen, möchten Sie möglicherweise async ausführen und den Leistungsvorteil sehen.

Es ist gut für die Skalierbarkeit, die mehrere Server einbezieht.

Also für z.B. Wenn das SearchRecordAsync sein SQL an die Datenbank sendet, gibt es eine unvollständige Aufgabe zurück, und wenn die Anfrage die Wartezeit erreicht, gibt sie das Anfragethread an den Thread-Pool zurück. Später, wenn die DB-Operation abgeschlossen ist, wird ein Anfrage-Thread aus dem Thread-Pool genommen und zum Fortsetzen der Anfrage verwendet.

Selbst wenn Sie keine SQL-Operationen verwenden, sagen wir, Sie möchten eine E-Mail an 10 Personen senden. In diesem Fall ist auch async sinnvoller.

Async ist auch sehr praktisch, um den Fortschritt eines langen Events anzuzeigen. So erhält der Benutzer immer noch die aktive GUI, während die Aufgabe im Hintergrund läuft.

Um zu verstehen, sehen Sie sich bitte dieses Beispiel an.

Hier versuche ich eine Aufgabe namens Mail senden zu starten. Interim Ich möchte die Datenbank aktualisieren, während der Hintergrund die Mail-Aufgabe sendet.

Sobald die Datenbankaktualisierung stattgefunden hat, wartet sie darauf, dass die Sende-Mail-Aufgabe abgeschlossen wird. Bei diesem Ansatz ist es jedoch klar, dass ich eine Aufgabe im Hintergrund ausführen und trotzdem mit dem ursprünglichen (Haupt-) Thread fortfahren kann.

%Vor%     
codebased 18.09.2014 00:21
quelle
0

Die Verwendung von async auf Ihrem Server kann die Skalierbarkeit erheblich verbessern, da der Thread, der die Anforderung zur Verarbeitung anderer Anforderungen bereitstellt, während die async -Operation ausgeführt wird, frei wird. In einem synchronen E / A-Betrieb würde der Thread beispielsweise ausgesetzt werden und nichts tun, bis die Operation abgeschlossen ist und nicht verfügbar wäre, um eine weitere Anfrage zu bedienen.

Das heißt, wenn Sie Task.Factory.StartNew verwenden, wird ein anderer Thread gestartet , sodass Sie die Skalierbarkeitsvorteile überhaupt nicht nutzen können. Ihr ursprünglicher Thread kann wiederverwendet werden, aber Sie haben die Arbeit in einen anderen Thread ausgelagert, sodass es überhaupt keinen Nettovorteil gibt. Tatsächlich kostet es, zu einem anderen Thread zu wechseln, aber das ist minimal.

Wirklich asynchrone Operationen starten keinen Thread und ich würde prüfen, ob ein solcher Vorgang existiert oder ob man für Request.CreateResponse schreiben kann. Dann wäre Ihr Code viel besser skalierbar. Wenn nicht, sind Sie besser dran mit dem synchronen Ansatz.

    
Ned Stoyanov 18.09.2014 00:34
quelle