Pregunta

Digamos que tengo tres tareas, a, b, y c.Se garantiza que los tres generarán 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 cualquier tarea que falle primero.ya que no hay try...catch aquí, esta excepción aparecerá en algún otro lugar de mi código.

¿Qué sucede cuando las dos tareas restantes generan una excepción?¿No son estas excepciones no observadas las que provocarán la finalización de todo el proceso?¿Eso significa que la única forma de utilizar WhenAny está dentro de un try...catch bloquear y luego observar de alguna manera las dos tareas restantes antes de continuar?

Hacer un seguimiento: Me gustaría que la respuesta se aplique tanto a .NET 4.5 y .NET 4.0 con Async Targeting Pack (aunque claramente usando TaskEx.WhenAny en ese caso).

¿Fue útil?

Solución

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

Aquellos Tasks se completará en un estado defectuoso.

¿No son estas excepciones no observadas las que provocarán la finalización de todo el proceso?

Ya no.

En .NET 4.0, el Task el destructor pasaría su excepción no observada a TaskScheduler.UnobservedTaskException, lo que finalizaría el proceso si no se controla.

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

Otros consejos

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

Normalmente escribo un método auxiliar para tareas de disparar y olvidar 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 inicio de sesión en aplicaciones de producción.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top