Wie Async und Await funktioniert

7

Ich versuche zu verstehen, wie Async und Await funktionieren. Wie steuern Reisen im Programm. Hier ist der Code, den ich zu verstehen versuchte.

%Vor%

Wenn ein Knopfklick erfolgt, wird MyMethod() aufgerufen und von MyMethod LongRunningOperation() wird aufgerufen und es dauert 5 Sekunden bis zum Abschluss. also meine Frage ist

  • Was bedeutet diese Zeile?

    Task longRunningTask = LongRunningOperation ();

  • Was das bedeutet int result = await longRunningTask;

Die obige Zeile könnte festgeschrieben werden und eine Zeile wie

%Vor%

oder

%Vor%

Bitte kann mir jemand den obigen Code erklären, der mir nicht klar ist.

1) Wenn die longRunningOperation noch nicht beendet ist und noch läuft, kehrt MyMethod () zu seiner aufrufenden Methode zurück, wodurch der Hauptthread nicht blockiert wird. Wenn die longRunningOperation abgeschlossen ist, kehrt ein Thread vom ThreadPool (kann ein beliebiger Thread sein) zu MyMethod () im vorherigen Zustand zurück und setzt die Ausführung fort (in diesem Fall wird das Ergebnis an die Konsole ausgegeben).

Ein zweiter Fall wäre, dass die longRunningOperation ihre Ausführung bereits beendet hat und das Ergebnis verfügbar ist. Wenn der Compiler longRunningOperation erreicht, weiß der Compiler, dass er das Ergebnis hat und weiterhin Code auf demselben Thread ausführen wird. (In diesem Fall Druckergebnis zur Konsole).

Punkt 1 ist mir gar nicht klar wie die Aussage " if the longRunningOperation hasn't finished and is still running, MyMethod() will return to its calling method "

Wenn möglich, erläutern Sie den Punkt genauer. Danke

    
Thomas 12.03.2014, 10:52
quelle

3 Antworten

15

Ich habe eine async Einführung in meinem Blog, die Sie vielleicht hilfreich finden .

Dieser Code:

%Vor%

ist im Wesentlichen dasselbe wie dieser Code:

%Vor%

Also, ja, LongRunningOperation wird direkt von dieser Methode aufgerufen.

Wenn dem Operator await eine bereits abgeschlossene Aufgabe übergeben wird, wird das Ergebnis extrahiert und die Methode (synchron) ausgeführt.

Wenn dem Operator await eine unvollständige Aufgabe übergeben wurde (z. B. ist die von LongRunningOperation zurückgegebene Aufgabe nicht abgeschlossen), erfasst await standardmäßig den aktuellen Kontext und gibt eine unvollständige Aufgabe von der Methode zurück.

Später, wenn die await Aufgabe abgeschlossen ist, wird der Rest der Methode in diesem Kontext ausgeführt.

Dieser "Kontext" ist SynchronizationContext.Current , es sei denn, es ist null , in diesem Fall ist es TaskScheduler.Current . Wenn Sie dies in einer Konsolenanwendung ausführen, ist der Kontext normalerweise der Threadpoolkontext. Daher wird die Methode async die Ausführung in einem Threadpool-Thread fortsetzen. Wenn Sie jedoch die gleiche Methode für einen Benutzeroberflächenthread ausführen, ist der Kontext ein UI-Kontext, und die async -Methode wird wieder im UI-Thread ausgeführt.

    
Stephen Cleary 12.03.2014, 11:31
quelle
16

Ich habe es auf die folgende Weise gelernt, ich fand es eine klare und prägnante Erklärung:

%Vor%

Wenn Method aufgerufen wird, wird der Inhalt ( code; lines) bis await something; ausgeführt. An diesem Punkt wird something; ausgelöst und die Methode endet wie ein return; war dort.

something; tut was es braucht und kehrt dann zurück.

Wenn something; zurückkehrt, kehrt die Ausführung zu Method zurück und läuft von await weiter, wobei moreCode;

ausgeführt wird

In noch mehr schematischer Weise passiert hier Folgendes:

  1. Methode wird aufgerufen
  2. code; wird ausgeführt
  3. something; wird ausgeführt, der Ablauf kehrt zu dem Punkt zurück, an dem Method aufgerufen wurde
  4. Ausführung geht weiter mit dem, was nach dem Method Aufruf
  5. kommt
  6. Wenn something; zurückgibt, kehrt der Ablauf in Method zurück
  7. moreCode; wird ausgeführt und Method selbst endet (ja, es könnte auch etwas anderes await -ing geben, und so weiter)
Alex 12.03.2014 11:03
quelle
4

Hinter den Kulissen konvertiert der C # -Compiler Ihren Code in eine Zustandsmaschine. Es erzeugt viel mehr Code, so dass hinter den Kulissen jedes Mal, wenn eine wartende Aufgabe oder eine asynchrone Aktion abgeschlossen wird, die Ausführung dort fortgesetzt wird, wo sie aufgehört hat. In Bezug auf Ihre Frage wird die asynchrone Methode jedes Mal, wenn die asynchrone Aktion beendet ist, beim aufrufenden Thread aufgerufen, wenn Sie den Aufruf der asynchronen Methode ursprünglich gestartet haben. ZB wird Ihr Code in dem Thread ausgeführt, auf dem Sie begonnen haben. Daher wird die asynchrone Aktion in einem Task-Thread ausgeführt, dann wird das Ergebnis in dem Thread zurückgegeben, in dem die Methode ursprünglich aufgerufen wurde, und weiter ausgeführt.

await ruft den Wert aus der Task oder async Aktion ab und "entpackt" ihn von der Task, wenn die Ausführung zurückgegeben wird. In diesem Fall wird er automatisch in den int Wert gesetzt, so dass die Aufgabe nicht gespeichert werden muss.

Ihr Code hat das Problem, wo er in der LongRunningTask () erwartet wird, dass Sie wahrscheinlich nur die lange Task-Methode ohne den Async zurückgeben möchten, dann lassen Sie Ihre MyMethod die Wartezeit erfüllen.

int Wert = erwartet LongWaitingTask ()

Ссылка

Es ist eine Voraussetzung für asynchrone Methoden, dass Sie eine Aufgabe oder void zurückgeben.

Es ist möglich, es zu ändern, wenn Sie von der Ausführung der asynchronen Task zurückkehren, wird der restliche Code in dem Thread ausgeführt, in dem die asynchrone Task ausgeführt wurde. Ссылка

    
Glenn Watson 12.03.2014 11:01
quelle

Tags und Links