Frage Steht Async auf ein Keyword, das einem ContinueWith-Lambda entspricht?


Könnte jemand bitte freundlich genug sein, um zu bestätigen, ob ich das Async-Warten-Schlüsselwort richtig verstanden habe? (Mit Version 3 des CTP)

Bisher habe ich herausgearbeitet, dass das Einfügen des await-Schlüsselworts vor einem Methodenaufruf im Wesentlichen zwei Dinge beinhaltet: A. Es erzeugt eine sofortige Rückgabe und B. Es erstellt eine "Fortsetzung", die nach Abschluss des asynchronen Methodenaufrufs aufgerufen wird. In jedem Fall ist die Fortsetzung der Rest des Codeblocks für die Methode.

Ich frage mich also, ob diese beiden Bits technisch gleichwertig sind, und wenn ja, bedeutet das im Grunde, dass das Schlüsselwort await identisch mit der Erstellung eines ContinueWith Lambda ist (dh es ist im Grunde eine Compiler-Verknüpfung für einen)? Wenn nicht, was sind die Unterschiede?

bool Success =
    await new POP3Connector(
        "mail.server.com", txtUsername.Text, txtPassword.Text).Connect();
// At this point the method will return and following code will
// only be invoked when the operation is complete(?)
MessageBox.Show(Success ? "Logged In" : "Wrong password");

VS

(new POP3Connector(
    "mail.server.com", txtUsername.Text, txtPassword.Text ).Connect())
.ContinueWith((success) =>
    MessageBox.Show(success.Result ? "Logged In" : "Wrong password"));

76
2018-01-07 03:53


Ursprung


Antworten:


Die allgemeine Idee ist richtig - der Rest der Methode wird zu einer Art Fortsetzung gemacht.

Das Blogpost "schneller Weg" hat Details darüber, wie die async/await Compiler-Transformation funktioniert.

Unterschiede, aus dem Kopf:

Das await Stichwort verwendet auch ein "Scheduling Kontext" -Konzept. Der Planungskontext ist SynchronizationContext.Current wenn es existiert, fällt es zurück TaskScheduler.Current. Die Fortsetzung wird dann im Planungskontext ausgeführt. Also wäre eine nähere Annäherung zu bestehen TaskScheduler.FromCurrentSynchronizationContext in ContinueWithzurückfallen TaskScheduler.Current Falls benötigt.

Das tatsächliche async/await die Implementierung basiert auf dem Mustervergleich; es verwendet ein "erwartbares" Muster, das andere Dinge außer Aufgaben erwarten lässt. Einige Beispiele sind die asynchronen WinRT-APIs, einige spezielle Methoden wie z Yield, Rx Observablen und spezielle Sockets erwarten, dass sie den GC nicht so hart treffen. Aufgaben sind mächtig, aber sie sind nicht die einzigen, die auf sie warten.

Ein kleinerer nitpicky Unterschied kommt in den Sinn: Wenn das Erwartete schon fertig ist, dann das async Methode kehrt an diesem Punkt nicht wirklich zurück; es läuft synchron weiter. Es ist also so, als würde man vorübergehen TaskContinuationOptions.ExecuteSynchronously, aber ohne die Stack-Probleme.


76
2018-01-07 04:39



Es ist "im Wesentlichen" das, aber der generierte Code tut mehr als nur das. Für viele weitere Details zum generierten Code empfehle ich Jon Skeets Eduasync-Serie:

http://codeblog.jonskeet.uk/category/eduasync/

Insbesondere geht Post # 7 in das, was generiert wird (ab CTP 2) und warum, also passt es wahrscheinlich gut zu dem, wonach Sie gerade suchen:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

EDIT: Ich denke, es ist wahrscheinlich mehr Details als das, was Sie von der Frage suchen, aber wenn Sie sich fragen, wie die Dinge aussehen, wenn Sie mehrere wartet in der Methode, das ist in Post # 9 abgedeckt :)

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/


8
2018-01-07 04:38