Est-ce que Task.Result est identique à .GetAwaiter.GetResult ()?

Je lisais récemment un code qui utilise beaucoup de méthodes asynchrones, mais il faut parfois les exécuter de manière synchrone. Le code fait:

Foo foo = GetFooAsync(...).GetAwaiter().GetResult(); 

Est-ce la même chose que

 Foo foo = GetFooAsync(...).Result; 

?

Plutôt. Une petite différence cependant: si la Task échoue, GetResult() lancera simplement l’exception provoquée directement, tandis que Task.Result lancera une exception AggregateException . Cependant, quel est l’intérêt d’utiliser l’un ou l’autre quand il est async ? La meilleure option 100x est d’ await .

De plus, vous n’êtes pas censé utiliser GetResult() . Il est destiné à être utilisé uniquement par le compilateur, pas pour vous. Mais si vous ne voulez pas l’exagérer AggregateException , utilisez-le.

https://github.com/aspnet/Security/issues/59

“Une dernière remarque: évitez autant que possible Task.Result et Task.Wait car ils encapsulent toujours l’exception interne dans une exception AggregateException et remplacent le message par une exception générique (une ou plusieurs erreurs se sont produites), ce qui rend le débogage plus difficile. Même si la version synchrone ne devrait pas être utilisée aussi souvent, vous devriez fortement envisager d’utiliser Task.GetAwaiter().GetResult() place. ”

http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html

GetResult ” signifie en fait “vérifier la tâche pour les erreurs”

En général, je fais de mon mieux pour éviter le blocage synchrone sur une tâche asynchrone. Cependant, il y a une poignée de situations où je viole cette directive. Dans ces rares conditions, ma méthode préférée est GetAwaiter().GetResult() car elle préserve les exceptions de tâches au lieu de les inclure dans une exception AggregateException .

http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4-5.aspx

Comme je l’ai mentionné précédemment, nous avons une barre de compatibilité très élevée, et nous avons donc évité de casser les changements. En tant que tel, Task.Wait conserve son comportement d’origine de toujours envelopper. Cependant, vous pouvez vous trouver dans des situations avancées où vous souhaitez un comportement similaire au blocage synchrone utilisé par Task.Wait , mais où vous souhaitez que l’exception d’origine soit propagée sans être enveloppée dans une exception AggregateException . Pour ce faire, vous pouvez directement cibler l’attendeur de la tâche. Lorsque vous écrivez “ await task; ”, Le compilateur traduit cela en utilisation de la méthode Task.GetAwaiter() , qui renvoie une instance qui a une méthode GetResult() . Lorsqu’elle est utilisée sur une tâche défaillante, GetResult() propage l’exception d’origine (c’est ainsi que « await task; »). Vous pouvez donc utiliser « task.GetAwaiter().GetResult() » si vous souhaitez appeler directement cette logique de propagation.

Une autre différence réside dans le fait que la fonction async ne renvoie que la Task au lieu de la Task alors vous ne pouvez pas utiliser

 GetFooAsync(...).Result; 

Tandis que

 GetFooAsync(...).GetAwaiter().GetResult(); 

fonctionne encore.

Je sais que l’exemple de code dans la question est pour le cas Task , cependant la question est généralement posée.