wake-up-neo.com

Ist Task.Result dasselbe wie .GetAwaiter.GetResult ()?

Ich habe kürzlich Code gelesen, der viele asynchrone Methoden verwendet, aber manchmal muss er synchron ausgeführt werden. Der Code macht:

Foo foo = GetFooAsync(...).GetAwaiter().GetResult();

Ist das das Gleiche wie

Foo foo = GetFooAsync(...).Result;

?

204
Jay Bazuzi

Ziemlich viel. Ein kleiner Unterschied ist jedoch: Wenn Task fehlschlägt, wird GetResult() die direkt verursachte Ausnahme auslösen, während Task.Result einen AggregateException auslöst. Welchen Sinn hat es jedoch, beide zu verwenden, wenn es async ist? Die 100x bessere Option ist die Verwendung von await.

Außerdem sollten Sie GetResult() nicht verwenden. Es ist nur für Compiler gedacht, nicht für Sie. Wenn Sie jedoch nicht das ärgerliche AggregateException möchten, verwenden Sie es.

122
It'sNotALie.

Task.GetAwaiter().GetResult() wird gegenüber Task.Wait und Task.Result bevorzugt, da es Ausnahmen weitergibt, anstatt sie in eine AggregateException zu packen. Alle drei Methoden können jedoch zu Deadlock-Problemen führen und sollten zu Gunsten von async/await vermieden werden.

Das folgende Zitat erklärt, warum Task.Wait und Task.Result nicht einfach das Ausnahmebreitungsverhalten von Task.GetAwaiter().GetResult() enthalten (aufgrund einer "sehr hohen Kompatibilitätsleiste").

Wie ich bereits erwähnt habe, haben wir eine sehr hohe Kompatibilitätsleiste, und so haben wir das Brechen von Änderungen vermieden. Als solches behält Task.Wait sein ursprüngliches Verhalten bei, immer zu verpacken. Es kann jedoch vorkommen, dass Sie sich in einigen fortgeschrittenen Situationen befinden, in denen Sie ein ähnliches Verhalten wie die von Task.Wait verwendete synchrone Blockierung wünschen, die ursprüngliche Ausnahme jedoch nicht in eine AggregateException eingeschlossen werden soll. Um dies zu erreichen, können Sie den Waititer der Task direkt ansprechen. Wenn Sie "await task;" schreiben, übersetzt der Compiler dies in die Verwendung der Task.GetAwaiter()-Methode, die eine Instanz mit einer GetResult()-Methode zurückgibt. Bei einer fehlerhaften Aufgabe verbreitet GetResult() die ursprüngliche Ausnahme (so erhält "await task;" sein Verhalten). Sie können also "task.GetAwaiter().GetResult()" verwenden, wenn Sie diese Ausbreitungslogik direkt aufrufen möchten.

https://blogs.msdn.Microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

"GetResult" bedeutet eigentlich "Task auf Fehler prüfen"

Im Allgemeinen versuche ich mein Bestes, um zu vermeiden, dass eine asynchrone Task synchron blockiert wird. Es gibt jedoch einige Situationen, in denen ich gegen diese Richtlinie verstoße. In diesen seltenen Fällen ist meine bevorzugte Methode GetAwaiter().GetResult(), da die Task-Ausnahmen beibehalten werden, anstatt sie in eine AggregateException zu packen.

http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html

66
Nitin Agarwal

https://github.com/aspnet/Security/issues/59

"Eine letzte Bemerkung: Sie sollten Task.Result und Task.Wait als Möglichst nicht verwenden, da sie die innere Ausnahme immer in einer AggregateException kapseln und die Nachricht durch eine generische ersetzen (ein oder Weitere Fehler aufgetreten). , was das Debuggen schwieriger macht. Selbst wenn die synchrone Version nicht so oft verwendet werden sollte, sollten Sie stattdessen Task.GetAwaiter().GetResult() in Betracht ziehen. "

61
scyuo

Ein weiterer Unterschied besteht darin, dass die async-Funktion nur Task anstelle von Task<T> zurückgibt und nicht verwendet werden kann

GetFooAsync(...).Result;

Wohingegen 

GetFooAsync(...).GetAwaiter().GetResult();

funktioniert noch.

Ich weiß, dass der Beispielcode in der Frage für den Fall Task<T> gilt, die Frage wird jedoch allgemein gestellt. 

26
Nuri Tasdemir

Wenn ein Task fehlerhaft ist, wird die Ausnahme erneut ausgelöst, wenn der Fortsetzungscode awaiter.GetResult () aufruft. Anstatt GetResult aufzurufen, könnten wir einfach auf die Result-Eigenschaft der Task zugreifen. Der Vorteil des Aufrufs von GetResult besteht darin, dass bei einem Fehler der Task die Ausnahme direkt ausgelöst wird, ohne in AggregateException eingeschlossen zu werden, was einfachere und sauberere catch-Blöcke ermöglicht.

Für nicht generische Tasks hat GetResult () einen ungültigen Rückgabewert. Seine nützliche Funktion besteht dann ausschließlich darin, Ausnahmen erneut zu werfen.

quelle: C # 7.0 in Kürze

0
Ali Abdollahi

Wie bereits erwähnt, wenn Sie await verwenden können. Wenn Sie den Code synchron ausführen müssen, wie Sie .GetAwaiter().GetResult() sagen, ist .Result oder .Wait() ein Risiko für Deadlocks, wie viele in Kommentaren/Antworten gesagt haben. Da die meisten von uns Oneliner mögen, können Sie diese für .Net 4.5< verwenden.

Erfassen eines Wertes über eine asynchrone Methode:

var result = Task.Run(() => asyncGetValue()).Result;

Synchrones Aufrufen einer asynchronen Methode

Task.Run(() => asyncMethod()).Wait();

Aufgrund der Verwendung von Task.Run treten keine Deadlock-Probleme auf.

Quelle:

https://stackoverflow.com/a/32429753/3850405

0
Ogglas