Qual é a diferença entre .Wait () vs .GetAwaiter (). GetResult ()?

88

Meu método retorna Task. Eu quero esperar até que termine. O que devo usar .Wait()ou .GetAwaiter().GetResult()? Qual a diferença entre eles?


fonte

Respostas:

107

Ambos são uma espera síncrona pelo resultado da operação (e você deve evitá-los, se possível).

A diferença está principalmente no tratamento de exceções. Com Wait, o rastreamento de pilha de exceção é inalterado e representa a pilha real no momento da exceção, então se você tem um pedaço de código que roda em um thread pool de threads, você tem uma pilha como

ThreadPoolThread.RunTask
YourCode.SomeWork

Por outro lado, .GetAwaiter().GetResult()retrabalhará o rastreamento de pilha para levar em consideração todo o contexto assíncrono, ignorando que algumas partes do código são executadas no encadeamento de IU e outras em um encadeamento ThreadPool e algumas são simplesmente E / S assíncronas. Portanto, seu rastreamento de pilha refletirá uma etapa semelhante à síncrona em seu código :

TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork

Isso tende a tornar os rastreamentos de pilha de exceção muito mais úteis, para dizer o mínimo. Você pode ver onde YourCode.SomeWorkfoi chamado no contexto de seu aplicativo , em vez de "a forma física como foi executado".

Um exemplo de como isso funciona está na fonte de referência (não contratual, é claro).

Luaan
fonte
6
Task.GetAwaiter () retorna um TaskAwaiter . No entanto, o documento para TaskAwaiter.GetResult () avisa: "Esta API oferece suporte à infraestrutura do produto e não se destina a ser usada diretamente em seu código." Você pode comentar?
DavidRR
23
@DavidRR O todo TaskAwaiteré um detalhe de implementação. Por outro lado, o mecanismo de espera / espera é documentado e usa digitação de pato - GetAwaiteré para awaitcomo GetEnumeratoré foreachou Disposeé para using. Tudo isso é definido na especificação C # independentemente do waititer em particular que está sendo usado - observe que Task.GetAwaiter"se destina ao uso do compilador em vez de ser usado no código do aplicativo" Mas o ponto é que o uso pretendido é fazer um await, não Wait()nem GetAwaiter().GetResult()- mas GetResultfornecer pilhas melhores se você precisar.
Luaan