Qual è la differenza tra .Wait () e .GetAwaiter (). GetResult ()?


89

Il mio metodo ritorna Task. Voglio aspettare che finisca. Cosa dovrei usare .Wait()o .GetAwaiter().GetResult()? Qual'è la differenza tra loro?

Risposte:


110

Entrambi sono un'attesa sincrona per il risultato dell'operazione (e dovresti evitarli se possibile).

La differenza sta principalmente nella gestione delle eccezioni. Con Wait, la traccia dello stack delle eccezioni è inalterata e rappresenta lo stack effettivo al momento dell'eccezione, quindi se hai una parte di codice che viene eseguita su un thread del pool di thread, avresti uno stack come

ThreadPoolThread.RunTask
YourCode.SomeWork

D'altra parte, .GetAwaiter().GetResult()rielaborerà la traccia dello stack per prendere in considerazione tutto il contesto asincrono, ignorando che alcune parti del codice vengono eseguite sul thread dell'interfaccia utente e alcune su un thread ThreadPool e alcune sono semplicemente I / O asincrono. Quindi la traccia dello stack rifletterà un passaggio simile a quello sincrono nel codice :

TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork

Questo tende a rendere le tracce dello stack delle eccezioni molto più utili, per non dire altro. Puoi vedere dove è YourCode.SomeWorkstato chiamato nel contesto della tua applicazione , piuttosto che "il modo fisico in cui è stato eseguito".

Un esempio di come funziona è nella fonte di riferimento (non contrattuale, ovviamente).


6
Task.GetAwaiter () restituisce un TaskAwaiter . Tuttavia, il documento per TaskAwaiter.GetResult () consiglia: "Questa API supporta l'infrastruttura del prodotto e non è concepita per essere utilizzata direttamente dal codice." Puoi commentare?
DavidRR

24
@DavidRR L'intero TaskAwaiterè un dettaglio di implementazione. D'altra parte, il meccanismo di attesa / attesa è documentato e utilizza la digitazione a papera: GetAwaiterè awaitcome GetEnumeratorè foreacho Disposeè using. Tutto questo è definito nella specifica C # indipendentemente dal particolare attendente utilizzato - si noti che Task.GetAwaiterè "destinato all'uso da parte del compilatore piuttosto che all'uso nel codice dell'applicazione". Ma il punto è che l'uso previsto è fare un await, non Wait()GetAwaiter().GetResult()- ma GetResultti dà pile più belle se ne hai bisogno.
Luaan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.