run method fake convert await async c# async-await

c# - method - ¿TaskResult es lo mismo que.GetAwaiter.GetResult()?



fake async c# (4)

Recientemente estuve leyendo un código que usa muchos métodos asíncronos, pero a veces es necesario ejecutarlos de forma síncrona. El código hace:

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

¿Es esto lo mismo que

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

?


Bastante. Sin embargo, una pequeña diferencia: si la Task falla, GetResult() arrojará la excepción causada directamente, mientras que Task.Result emitirá una AggregateException . Sin embargo, ¿de qué sirve usar cualquiera de esos cuando es async ? La mejor opción de 100x es usar await .

Además, no está destinado a usar GetResult() . Está destinado a ser solo para uso del compilador, no para ti. Pero si no quieres la molesta AggregateException , AggregateException .


Otra diferencia es cuando la función async devuelve solo Task vez de Task<T> luego no puede usar

GetFooAsync(...).Result;

Mientras

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

todavía funciona.

Sé que el código de ejemplo en la pregunta es para el caso Task<T> , sin embargo, la pregunta se hace en general.


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

" GetResult " en realidad significa "verificar errores en la tarea"

En general, hago mi mejor esfuerzo para evitar el bloqueo sincrónico en una tarea asincrónica. Sin embargo, hay un puñado de situaciones en las que violo esa pauta. En esas condiciones excepcionales, mi método preferido es GetAwaiter().GetResult() porque conserva las excepciones de la tarea en lugar de envolverlas en una AggregateException .

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

Como mencioné anteriormente, tenemos una barra de compatibilidad muy alta, y así hemos evitado los cambios. Como tal, Task.Wait conserva su comportamiento original de envoltura siempre. Sin embargo, puede encontrarse en situaciones avanzadas en las que desee un comportamiento similar al bloqueo sincrónico empleado por Task.Wait , pero donde desea que la excepción original se propague sin envolver en lugar de estar encerrada en una AggregateException . Para lograr eso, puedes dirigir el awaiter de la Tarea directamente. Cuando escribes " await task; ", El compilador lo traduce en el uso del método Task.GetAwaiter() , que devuelve una instancia que tiene un método GetResult() . Cuando se utiliza en una Tarea con GetResult() , GetResult() propagará la excepción original (así es como " await task; " obtiene su comportamiento). Por lo tanto, puede usar " task.GetAwaiter().GetResult() " si desea invocar directamente esta lógica de propagación.


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

"Una última observación: debe evitar usar Task.Result y Task.Wait tanto como sea posible ya que siempre encapsulan la excepción interna en una AggregateException y reemplazan el mensaje por uno genérico (se produjeron uno o más errores), lo que hace que la depuración sea más difícil. . Incluso si la versión síncrona no se debe usar con Task.GetAwaiter().GetResult() frecuencia, debería considerar usar Task.GetAwaiter().GetResult() lugar. "