¿Bajo qué escenarios uno querría usar
public async Task AsyncMethod(int num)
en vez de
public async void AsyncMethod(int num)
El único escenario en el que puedo pensar es si necesita la tarea para poder seguir su progreso.
Además, en el siguiente método, ¿son innecesarias las palabras clave asíncronas y en espera?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
c#
asynchronous
.net-4.5
usuario981225
fuente
fuente
Foo()
seríaFooAsync()
.Thread.Sleep
con tus tareas que deberías en suawait Task.Delay(num)
lugarTask.Delay
no esTask.AsyncDelay
que todos los métodos en la tarea sean asíncronosasync void
lugarasync Task
. El método se bloqueó porque estaba usando un objeto de contexto de Entity Framework declarado como miembro del controlador antes de que el método terminara de ejecutarse. El marco eliminó el controlador antes de que su método terminara de ejecutarse. Cambié el método a Tarea asíncrona y funcionó.Respuestas:
1) Normalmente, desearía devolver a
Task
. La principal excepción debería ser cuando necesita tener unvoid
tipo de retorno (para eventos). Si no hay ninguna razón para no permitir que la persona que llama realiceawait
su tarea, ¿por qué no la permite?2) los
async
métodos que regresanvoid
son especiales en otro aspecto: representan operaciones asincrónicas de nivel superior y tienen reglas adicionales que entran en juego cuando su tarea devuelve una excepción. La forma más fácil es mostrar la diferencia con un ejemplo:f
La excepción es siempre "observada". Una excepción que deja un método asincrónico de nivel superior simplemente se trata como cualquier otra excepción no controlada.g
La excepción nunca se observa. Cuando el recolector de basura viene a limpiar la tarea, ve que la tarea resultó en una excepción, y nadie manejó la excepción. Cuando eso sucede, elTaskScheduler.UnobservedTaskException
controlador se ejecuta. Nunca debes dejar que esto suceda. Para usar tu ejemplo,Sí, use
async
yawait
aquí, se aseguran de que su método aún funcione correctamente si se produce una excepción.Para obtener más información, consulte: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
fuente
f
lugar deg
en mi comentario. La excepción def
se pasa aSynchronizationContext
.g
aumentaráUnobservedTaskException
, peroUTE
ya no bloquea el proceso si no se maneja. Hay algunas situaciones en las que es aceptable tener "excepciones asincrónicas" como esta que se ignoran.WhenAny
variosTask
correos electrónicos que resultan en excepciones. A menudo solo tiene que manejar el primero, y a menudo quiere ignorar a los demás.WhenAny
en primer lugar si está bien ignorar las otras excepciones: el caso de uso principal que tengo para él todavía termina esperando las tareas restantes cuando finalice alguna. , con o sin una excepción.Me he encontrado con este artículo muy útil sobre
async
yvoid
escrito por Jérôme Laban: https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void .htmlLa conclusión es que un
async+void
sistema puede bloquear el sistema y, por lo general, solo debe usarse en los controladores de eventos secundarios de la interfaz de usuario.fuente
Tengo una idea clara de estas declaraciones.
Las excepciones de un método de vacío asíncrono no se pueden atrapar con Catch
Estas excepciones se pueden observar usando AppDomain.UnhandledException o un evento general similar para aplicaciones GUI / ASP.NET, pero el uso de esos eventos para el manejo regular de excepciones es una receta para la imposibilidad de mantenimiento (bloquea la aplicación).
Los métodos de vacío asíncrono tienen diferentes semánticas de composición. Los métodos asíncronos que devuelven Tarea o Tarea pueden componerse fácilmente usando await, Task.WhenAny, Task.WhenAll, etc. Los métodos asíncronos que devuelven nulo no proporcionan una manera fácil de notificar al código de llamada que han completado. Es fácil iniciar varios métodos de vacío asíncrono, pero no es fácil determinar cuándo han terminado. Los métodos de vacío asíncrono notificarán su SynchronizationContext cuando comiencen y terminen, pero un SynchronizationContext personalizado es una solución compleja para el código de aplicación normal.
El método Async Void es útil cuando se usa el controlador de eventos síncronos porque generan sus excepciones directamente en el SynchronizationContext, que es similar a cómo se comportan los controladores de eventos síncronos
Para obtener más detalles, consulte este enlace https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
fuente
El problema con llamar a async void es que ni siquiera recupera la tarea, no tiene forma de saber cuándo se completó la tarea de la función (consulte https://blogs.msdn.microsoft.com/oldnewthing/20170720-00/ ? p = 96655 )
Estas son las tres formas de llamar a una función asíncrona:
fuente
Creo que también puede usar
async void
para iniciar operaciones en segundo plano, siempre que tenga cuidado de detectar excepciones. Pensamientos?fuente
Mi respuesta es simple: no puedes esperar método nulo
Entonces, si el método es asíncrono, es mejor estar atento, ya que puede perder la ventaja asíncrona.
fuente
De acuerdo con la documentación de Microsoft , NUNCA debe usar
async void
fuente