whenall example c# .net task-parallel-library .net-4.5 async-await

c# - example - Task.WhenAny y excepciones no observadas



task list c# (2)

Digamos que tengo tres tareas, a , b , y c . Los tres están garantizados para lanzar una excepción en un tiempo aleatorio entre 1 y 5 segundos. Luego escribo el siguiente código:

await Task.WhenAny(a, b, c);

En última instancia, esto generará una excepción de las faltas de tarea primero. Ya que no hay ningún try...catch aquí, esta excepción se propagará a otro lugar en mi código.

¿Qué sucede cuando las dos tareas restantes lanzan una excepción? ¿No son estas excepciones no observadas, que causarán la muerte de todo el proceso? ¿ WhenAny significa que la única forma de usar WhenAny es dentro de un bloque try...catch , y luego observar las dos tareas restantes antes de continuar?

Seguimiento: me gustaría que la respuesta se aplique tanto a .NET 4.5 como a .NET 4.0 con el paquete de objetivos de Async (aunque claramente use TaskEx.WhenAny en ese caso).


¿Qué sucede cuando las dos tareas restantes lanzan una excepción?

Esas Task se completarán en un estado de falla.

¿No son estas excepciones no observadas, que causarán la muerte de todo el proceso?

Ya no.

En .NET 4.0, el TaskScheduler.UnobservedTaskException Task pasaría su excepción no observada a TaskScheduler.UnobservedTaskException , que terminaría el proceso si no se manejaba.

En .NET 4.5, este comportamiento fue cambiado . Ahora, las excepciones no observadas se pasan a TaskScheduler.UnobservedTaskException , pero luego se ignoran si no se manejan.


Sí, las excepciones de tareas restantes no se observan. Pre .NET 4.5 está obligado a observarlos (no está seguro de cómo está la situación en .NET 4.5, pero cambió).

Por lo general, me escribo a mí mismo un método auxiliar para tareas de fuego y olvido como estas:

public static void IgnoreUnobservedExceptions(this Task task) { if (task.IsCompleted) { if (task.IsFaulted) { var dummy = task.Exception; } return; } task.ContinueWith(t => { var dummy = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously); }

Es posible que desee incluir el registro en aplicaciones de producción.