warten task.run vs erwarten c #

8

Ich habe das Web durchsucht und viele Fragen zu task.run vs async abgewartet, aber es gibt dieses spezielle Anwendungsszenario, in dem ich den Unterschied nicht wirklich verstehe. Szenario ist ziemlich einfach, glaube ich.

%Vor%

vs

%Vor%

Dabei ist LongProcess eine asynchrone Methode mit einigen asynchronen Aufrufen, wie zum Beispiel der Aufruf von db mit awarte ExecuteReaderAsync ().

Frage:

Gibt es in diesem Szenario einen Unterschied zwischen den beiden? Jede Hilfe oder Eingabe geschätzt, danke!

    
mattias 03.08.2016, 09:18
quelle

2 Antworten

8

Task.Run darf die Operation für die Verarbeitung in einem anderen Thread posten. Das ist der einzige Unterschied.

Dies kann nützlich sein - wenn zum Beispiel LongProcess nicht wirklich asynchron ist, wird der Aufrufer schneller zurückkommen. Aber für eine wirklich asynchrone Methode macht es keinen Sinn, Task.Run zu verwenden, und dies kann zu unnötigem Verschwendung führen.

Seien Sie jedoch vorsichtig, da sich das Verhalten von Task.Run basierend auf der Überladungsauflösung ändert. In Ihrem Beispiel wird die Überladung Func<Task> gewählt, die (richtigerweise) auf den Abschluss von LongProcess wartet. Wenn jedoch ein Delegat ohne Aufgabe verwendet wird, wartet Task.Run nur auf die Ausführung bis zum ersten await (beachten Sie, dass sich TaskFactory.StartNew immer verhält, also don nutze das nicht).

    
Luaan 03.08.2016, 09:20
quelle
8

Sehr oft denken Leute, dass async-wait von mehreren Threads erledigt wird. Tatsächlich wird alles durch einen Thread erledigt.

Die Sache, die mir sehr geholfen hat, async-wait zu verstehen, ist dieses Interview mit Eric Lippert über async-erwarten . Irgendwo in der Mitte vergleicht er async mit einem Koch, der warten muss, bis etwas Wasser kocht. Anstatt nichts zu tun, schaut er sich um, ob es noch etwas anderes zu tun gibt, wie die Zwiebeln zu schneiden. Wenn das beendet ist und das Wasser immer noch nicht kocht, prüft er, ob noch etwas zu tun ist, und so weiter, bis er nichts anderes zu tun hat, als zu warten. In diesem Fall kehrt er zu der ersten Sache zurück, auf die er gewartet hat.

Wenn Ihre Prozedur eine erwartete Funktion aufruft, sind wir sicher, dass irgendwo in dieser erwarteten Funktion ein Aufruf einer erwarteten Funktion erfolgt, andernfalls wäre die Funktion nicht zu erwarten. In der Tat wird Ihr Compiler Sie warnen, wenn Sie vergessen haben, irgendwo in Ihrer erwarteten Funktion zu warten.

Wenn Ihre erwartete Funktion die andere erwartete Funktion aufruft, dann tritt der Thread in diese andere Funktion ein und beginnt mit den Dingen in dieser Funktion und geht tiefer in andere Funktionen, bis er eine Wartezeit erfüllt.

Anstatt auf die Ergebnisse zu warten, geht der Thread in seinem Aufruf-Stack nach oben, um zu sehen, ob es weitere Code-Stücke gibt, die er verarbeiten kann, bis er ein Warten sieht. Geh wieder in den Call-Stack, bearbeite bis zum Warten, usw. Sobald alle warten, sucht der Thread nach dem unteren warten und setzt fort, sobald dies abgeschlossen ist.

Das hat den Vorteil, dass, wenn der Aufrufer Ihrer erwarteten Funktion nicht das Ergebnis Ihrer Funktion benötigt, aber andere Dinge tun kann, bevor das Ergebnis benötigt wird, können diese anderen Dinge vom Thread erledigt werden, anstatt in Ihrem zu warten Funktion.

Ein Anruf, ohne sofort auf das Ergebnis zu warten, würde so aussehen:

%Vor%

Beachten Sie, dass in diesem Szenario alles von einem Thread erledigt wird. Solange dein Thread etwas zu tun hat, wird er beschäftigt sein.

  

Addition. Es ist nicht wahr, dass nur ein Thread beteiligt ist. Jeder Thread, der nichts zu tun hat, kann nach einer Wartezeit mit der Verarbeitung des Codes fortfahren. Wenn Sie die Thread-ID überprüfen, können Sie sehen, dass diese ID nach dem Warten geändert werden kann. Der fortlaufende Thread hat das gleiche context wie der ursprüngliche Thread, sodass Sie so tun können, als wäre es der ursprüngliche Thread. Sie müssen nicht nach InvokeRequired suchen, es müssen keine Mutexes oder kritische Abschnitte verwendet werden. Für Ihren Code ist das so, als ob es einen Thread gibt.

Der Link zum Artikel am Ende dieser Antwort erklärt etwas mehr über den Thread-Kontext

Sie werden erwartete Funktionen hauptsächlich dort sehen, wo ein anderer Prozess etwas tun muss, während Ihr Thread nur warten muss, bis die andere Sache fertig ist, wie Daten über das Internet senden, eine Datei speichern, mit einer Datenbank kommunizieren usw.

Allerdings müssen manchmal einige schwere Berechnungen durchgeführt werden, und Sie möchten, dass Ihr Thread frei ist, etwas anderes zu tun, etwa auf Benutzereingaben zu reagieren. In diesem Fall können Sie eine erwartete Aktion starten, als ob Sie eine asynchrone Funktion aufgerufen hätten.

%Vor%

Jetzt macht ein anderer Thread die schweren Berechnungen, während Ihr Thread frei ist, andere Dinge zu tun. Sobald es beginnt zu warten, kann der Anrufer Dinge tun, bis er wartet. Effektiv kann Ihr Thread ziemlich frei auf Benutzereingaben reagieren. Dies wird jedoch nur dann der Fall sein, wenn alle darauf warten. Während Ihr Thread beschäftigt ist, Dinge zu tun, kann Ihr Thread nicht auf Benutzereingaben reagieren. Stellen Sie daher immer sicher, dass Sie, wenn Sie glauben, dass Ihr UI-Thread einige Zeit mit der Verarbeitung beschäftigt sein muss, Task.Run verwenden und einen anderen Thread tun lassen müssen

Ein weiterer Artikel, der mir geholfen hat: Async-Await von dem brillanten Erklärer Stephen Cleary

    
Harald Coppoolse 03.08.2016 20:29
quelle

Tags und Links