Was ist der Unterschied zwischen .Wait () und .GetAwaiter (). GetResult ()?

89

Meine Methode kehrt zurück Task. Ich möchte warten, bis es fertig ist. Was soll ich verwenden .Wait()oder .GetAwaiter().GetResult()? Was ist der Unterschied zwischen ihnen?


quelle

Antworten:

110

Beides ist ein synchrones Warten auf das Ergebnis der Operation (und Sie sollten diese nach Möglichkeit vermeiden).

Der Unterschied besteht hauptsächlich in der Behandlung von Ausnahmen. Mit Waitist die Ablaufverfolgung des Ausnahmestapels unverändert und stellt den tatsächlichen Stapel zum Zeitpunkt der Ausnahme dar. Wenn Sie also einen Code haben, der auf einem Thread-Pool-Thread ausgeführt wird, haben Sie einen Stapel wie

ThreadPoolThread.RunTask
YourCode.SomeWork

Auf der anderen Seite .GetAwaiter().GetResult()wird der Stack-Trace überarbeitet, um den gesamten asynchronen Kontext zu berücksichtigen. Dabei wird ignoriert, dass einige Teile des Codes auf dem UI-Thread und einige auf einem ThreadPool-Thread ausgeführt werden und andere einfach asynchrone E / A sind. Ihre Stapelverfolgung spiegelt also einen synchronen Schritt durch Ihren Code wider :

TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork

Dies macht Ausnahme-Stack-Traces, gelinde gesagt, viel nützlicher. Sie können sehen, wo im Kontext Ihrer AnwendungYourCode.SomeWork aufgerufen wurde , und nicht "wie sie physisch ausgeführt wurde".

Ein Beispiel dafür ist die Referenzquelle (natürlich nicht vertraglich).

Luaan
quelle
6
Task.GetAwaiter () gibt einen TaskAwaiter zurück . Im Dokument für TaskAwaiter.GetResult () wird jedoch Folgendes empfohlen : "Diese API unterstützt die Produktinfrastruktur und ist nicht für die direkte Verwendung in Code vorgesehen." Kannst du einen Kommentar abgeben?
DavidRR
24
@DavidRR Das Ganze TaskAwaiterist ein Implementierungsdetail. Auf der anderen Seite ist der Mechanismus "Warten / Warten" dokumentiert und verwendet die Enten-Typisierung - GetAwaiterist awaitwie zu GetEnumeratorist foreachoder Disposeist zu using. All dies ist in der C # -Spezifikation unabhängig vom verwendeten Kellner definiert. Beachten Sie, dass dies Task.GetAwaiter"eher für die Verwendung durch den Compiler als für die Verwendung im Anwendungscode vorgesehen ist". Aber der Punkt ist, dass die beabsichtigte Verwendung darin besteht, ein await, nicht Wait()noch GetAwaiter().GetResult()- aber GetResultgibt Ihnen schönere Stapel, wenn Sie es brauchen.
Luaan