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 unaAggregateException
.
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 porTask.Wait
, pero donde desea que la excepción original se propague sin envolver en lugar de estar encerrada en unaAggregateException
. Para lograr eso, puedes dirigir el awaiter de la Tarea directamente. Cuando escribes "await task;
", El compilador lo traduce en el uso del métodoTask.GetAwaiter()
, que devuelve una instancia que tiene un métodoGetResult()
. Cuando se utiliza en una Tarea conGetResult()
,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
yTask.Wait
tanto como sea posible ya que siempre encapsulan la excepción interna en unaAggregateException
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 conTask.GetAwaiter().GetResult()
frecuencia, debería considerar usarTask.GetAwaiter().GetResult()
lugar. "