Niedawno czytałem jakiś kod, który używa wielu metod asynchronicznych, ale czasem muszę je wykonywać synchronicznie. Kod:
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
Czy to to samo co
Foo foo = GetFooAsync(...).Result;
c#
async-await
Jay Bazuzi
źródło
źródło
GetResult
: „Ten typ i jego członkowie są przeznaczone do użytku przez kompilator”. Inna osoba nie powinna go używać.async
/await
w MVC)Odpowiedzi:
Dosyć. Jedna mała różnica: jeśli
Task
zawiedzie,GetResult()
po prostu wyrzuci wyjątek spowodowany bezpośrednio, aTask.Result
wyrzuciAggregateException
. Jaki jest jednak sens używania któregoś z nich, kiedy jestasync
? 100 razy lepsza opcja to użycieawait
.Ponadto nie masz zamiaru używać
GetResult()
. Jest przeznaczony wyłącznie do użytku kompilatora, a nie dla ciebie. Ale jeśli nie chcesz denerwowaćAggregateException
, skorzystaj z niego.źródło
async Task
testy jednostek wsparcia i mają już jakiś czas.The 100x better option is to use await.
Nienawidzę takich stwierdzeń, gdybym mógł uderzyćawait
przed nimi, zrobiłbym to. Ale kiedy próbuję zmusić kod asynchroniczny do pracy z kodem niesynchronicznym, jak to, co często zdarza mi się często w Xamarin, ostatecznie muszę używać takich rzeczyContinueWith
, aby nie zakleszczyć interfejsu użytkownika. Edycja: Wiem, że to stare, ale to nie zmniejsza mojej frustracji ze znalezienia odpowiedzi, które twierdzą, że nie ma alternatywy dla sytuacji, w których nie można po prostu użyćawait
.Task.GetAwaiter().GetResult()
jest korzystniejszyTask.Wait
iTask.Result
ponieważ propaguje wyjątki zamiast owijając je wAggregateException
. Jednak wszystkie trzy metody powodują potencjalne problemy z zakleszczeniem i brakiem puli wątków. Wszystkich należy unikać na korzyśćasync/await
.Poniższy cytat wyjaśnia dlaczego
Task.Wait
aTask.Result
nie po prostu zawierać zachowanie propagacji wyjątkiemTask.GetAwaiter().GetResult()
(ze względu na „bardzo wysokim barze zgodności”).https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/
http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html
źródło
Task.GetAwaiter().GetResult()
jest to równoważne zawait task
. Zakładam, że pierwsza opcja jest używana, gdy metody nie można oznaczyćasync
(na przykład konstruktorem). Czy to jest poprawne? Jeśli tak, to koliduje z najwyższą odpowiedzią @ It'sNotALieTask.GetAwaiter().GetResult()
jest bardziej równoważneTask.Wait
iTask.Result
(w tym sensie, że wszystkie trzy będą blokować synchronicznie i potencjalnie mogą zostać zakleszczone), aleTask.GetAwaiter().GetResult()
ma wyjątkowe zachowanie propagacji oczekiwania na zadanie.https://github.com/aspnet/Security/issues/59
źródło
Task.WhenAll(task1, task2).GetAwaiter().GetResult();
.Kolejna różnica polega na tym, że
async
funkcja zwraca tylkoTask
zamiastTask<T>
tego nie można użyćNatomiast
nadal działa.
Wiem, że przykładowy kod w pytaniu dotyczy danej sprawy
Task<T>
, jednak pytanie jest zadawane ogólnie.źródło
Result
zGetIntAsync()
którego powracaTask<int>
nie tylkoTask
. Proponuję ponownie przeczytać moją odpowiedź.GetFooAsync(...).Result
wewnątrz funkcji, która powracaTask
. Ma to teraz sens, ponieważ w C # nie ma właściwości void (Task.Result
jest to właściwość), ale można oczywiście wywołać metodę void.Jak już wspomniano, jeśli możesz użyć
await
. Jeśli potrzebujesz uruchamiać kod synchronicznie, jak wspomniałeś.GetAwaiter().GetResult()
,.Result
lub.Wait()
istnieje ryzyko impasu, jak wielu powiedziało w komentarzach / odpowiedziach. Ponieważ większość z nas lubi onelinerów, możesz z nich korzystać.Net 4.5<
Pozyskiwanie wartości metodą asynchroniczną:
Synchroniczne wywoływanie metody asynchronicznej
Z powodu użycia nie wystąpią problemy z zakleszczeniem
Task.Run
.Źródło:
https://stackoverflow.com/a/32429753/3850405
źródło
źródło: c # 7.0 w pigułce
źródło