Moja metoda powraca Task
. Chcę poczekać, aż to się skończy. Czego powinienem użyć
.Wait()
lub .GetAwaiter().GetResult()
? Jaka jest różnica między nimi?
Moja metoda powraca Task
. Chcę poczekać, aż to się skończy. Czego powinienem użyć
.Wait()
lub .GetAwaiter().GetResult()
? Jaka jest różnica między nimi?
Oba są synchronicznym oczekiwaniem na wynik operacji (i należy ich unikać, jeśli to możliwe).
Różnica polega głównie na obsłudze wyjątków. W Wait
przypadku ślad stosu wyjątków jest niezmieniony i reprezentuje rzeczywisty stos w momencie wystąpienia wyjątku, więc jeśli masz fragment kodu działający w wątku puli wątków, masz stos taki jak
ThreadPoolThread.RunTask
YourCode.SomeWork
Z drugiej strony, .GetAwaiter().GetResult()
zmieni ślad stosu, aby uwzględnić cały kontekst asynchroniczny, ignorując, że niektóre części kodu są wykonywane w wątku interfejsu użytkownika, a niektóre w wątku puli wątków, a niektóre są po prostu asynchronicznymi we / wy. Więc twój ślad stosu będzie odzwierciedlał synchroniczny krok w kodzie :
TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork
To sprawia, że ślady stosu wyjątków są co najmniej bardziej przydatne. Możesz zobaczyć, gdzie YourCode.SomeWork
zostało wywołane w kontekście Twojej aplikacji , a nie „fizyczny sposób, w jaki została uruchomiona”.
Przykład tego, jak to działa, znajduje się w źródle referencyjnym (oczywiście poza umową).
TaskAwaiter
to szczegół implementacji. Z drugiej strony, mechanizm awaitable / awaiter jest udokumentowany i wykorzystuje pisanie typu kaczego -GetAwaiter
jest do tego,await
coGetEnumerator
jestforeach
lubDispose
jest dousing
. Wszystko to jest zdefiniowane w specyfikacji C # niezależnie od używanego konkretnego awaitera - uwaga, żeTask.GetAwaiter
jest „przeznaczone raczej do użytku przez kompilator niż do użycia w kodzie aplikacji”. Ale chodzi o to, że zamierzonym zastosowaniem jest wykonanie anawait
, a nieWait()
norGetAwaiter().GetResult()
- aleGetResult
daje ładniejsze stosy, jeśli tego potrzebujesz.