Ma méthode revient Task
. Je veux attendre la fin. Que dois-je utiliser
.Wait()
ou .GetAwaiter().GetResult()
? Quelle est la différence entre eux?
Ma méthode revient Task
. Je veux attendre la fin. Que dois-je utiliser
.Wait()
ou .GetAwaiter().GetResult()
? Quelle est la différence entre eux?
Réponses:
Les deux sont une attente synchrone du résultat de l'opération (et vous devez les éviter si possible).
La différence réside principalement dans la gestion des exceptions. Avec Wait
, la trace de pile d'exceptions n'est pas modifiée et représente la pile réelle au moment de l'exception, donc si vous avez un morceau de code qui s'exécute sur un thread de pool de threads, vous auriez une pile comme
ThreadPoolThread.RunTask
YourCode.SomeWork
D'autre part, .GetAwaiter().GetResult()
retravaillera la trace de la pile pour prendre en compte tout le contexte asynchrone, en ignorant que certaines parties du code s'exécutent sur le thread d'interface utilisateur, et d'autres sur un thread ThreadPool, et certaines sont simplement des E / S asynchrones. Ainsi, votre trace de pile reflétera une étape synchrone dans votre code :
TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork
Cela a tendance à rendre les traces de pile d'exceptions beaucoup plus utiles, c'est le moins qu'on puisse dire. Vous pouvez voir où a YourCode.SomeWork
été appelé dans le contexte de votre application , plutôt que "la manière physique dont elle a été exécutée".
Un exemple de la façon dont cela fonctionne est dans la source de référence (non contractuelle, bien sûr).
TaskAwaiter
est un détail d'implémentation. D'autre part, le mécanisme awaitable / de awaiter est documenté, et les utilisations de canard frappe - GetAwaiter
est await
comme GetEnumerator
c'est foreach
ou Dispose
est de using
. Tout cela est défini dans la spécification C # quel que soit le serveur particulier utilisé - notez qu'il Task.GetAwaiter
est "destiné à être utilisé par le compilateur plutôt qu'à être utilisé dans le code d'application". Mais le fait est que l'utilisation prévue est de faire un await
, pas Wait()
ni GetAwaiter().GetResult()
- mais GetResult
vous donne de plus belles piles si vous en avez besoin.