utilizar una try tipos sharp que practicas para net manejo manejar existen excepción excepciones errores ejemplos como catch buenas asp c# .net task-parallel-library task

c# - una - La forma correcta de manejar la excepción en la tarea continúa



que tipos de excepciones existen en c# (6)

Por favor, eche un vistazo al siguiente código:

static void Main(string[] args) { // Get the task. var task = Task.Factory.StartNew<int>(() => { return div(32, 0); }); // For error handling. task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted); // If it succeeded. task.ContinueWith(t => { Console.WriteLine(t.Result); }, TaskContinuationOptions.OnlyOnRanToCompletion); Console.ReadKey(); Console.WriteLine("Hello"); } private static int div(int x, int y) { if (y == 0) { throw new ArgumentException("y"); } return x / y; }

Si ejecuto el código en modo de lanzamiento, la salida es "Uno o más errores ocurrieron" y una vez que presiono la tecla "Enter", también aparece "Hello". Si ejecuto el código en modo de depuración, el resultado es el mismo que modo de liberación. Pero cuando se depura en IDE, aparece un mensaje de excepción IDE ("excepción no controlada en el código de usuario") cuando el control ejecuta la línea

throw new ArgumentException("y");

Si continúo desde allí, el programa no falla y muestra el mismo resultado que el modo de lanzamiento. ¿Es esta la forma correcta de manejar la excepción?



Como está utilizando tareas, debe obtener AggregateException que envuelve todas las excepciones ocurridas durante la ejecución. Verá One or more errors occurred , porque es el resultado predeterminado del método AggregateException.ToString() .

Necesitas el método Handle de la instancia de la excepción.

También vea el enfoque correcto para manejar tales excepciones here .


El "Uno o más errores ocurridos" proviene de una excepción de contenedor que realiza el grupo de tareas. Use Console.WriteLine(t.Exception.ToString()) para imprimir toda la excepción si la necesita.

Los IDE pueden capturar automáticamente todas las excepciones independientemente de si se manejaron o no.


Lo que tienes allí es una AggregateException . Esto se produce a partir de las tareas y requiere que verifique las excepciones internas para encontrar las específicas. Me gusta esto:

task.ContinueWith(t => { if (t.Exception is AggregateException) // is it an AggregateException? { var ae = t.Exception as AggregateException; foreach (var e in ae.InnerExceptions) // loop them and print their messages { Console.WriteLine(e.Message); // output is "y" .. because that''s what you threw } } }, TaskContinuationOptions.OnlyOnFaulted);


Probablemente no necesites manejadores de OnlyOnFaulted y OnlyOnRanToCompletion , y no estés manejando OnlyOnCanceled . Verifique esta respuesta para más detalles.

Pero cuando se depura en IDE, aparece un mensaje de excepción IDE ("excepción no controlada en el código de usuario") cuando el control ejecuta la línea

Verá la excepción en el depurador porque probablemente lo haya habilitado en las opciones de depuración / excepciones ( Ctrl + Alt + E ).

Si continúo desde allí, el programa no falla y muestra el mismo resultado que el modo de lanzamiento. ¿Es esta la forma correcta de manejar la excepción?

Una excepción que se lanzó pero no se manejó dentro de una acción Task no se relanzará automáticamente. En cambio, se envuelve para una observación futura como Task.Exception (de tipo AggregateException ). Puede acceder a la excepción original como Exception.InnerException :

Exception ex = task.Exception; if (ex != null && ex.InnerException != null) ex = ex.InnerException;

Para hacer que el programa se bloquee en este caso, realmente debe observar la excepción fuera de la acción de la tarea, por ejemplo, haciendo referencia a la Task.Result . Task.Result :

static void Main(string[] args) { // Get the task. var task = Task.Factory.StartNew<int>(() => { return div(32, 0); }); // For error handling. task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted); // If it succeeded. task.ContinueWith(t => { Console.WriteLine(t.Result); }, TaskContinuationOptions.OnlyOnRanToCompletion); Console.ReadKey(); Console.WriteLine("result: " + task.Result); // will crash here // you can also check task.Exception Console.WriteLine("Hello"); }

Más detalles: Tareas y excepciones no controladas , Manejo de excepciones de tareas en .NET 4.5 .

Actualizado para abordar el comentario: aquí es cómo lo haría en una aplicación de interfaz de usuario con .NET 4.0 y VS2010:

void Button_Click(object sender, EventArgs e) { Task.Factory.StartNew<int>(() => { return div(32, 0); }).ContinueWith((t) => { if (t.IsFaulted) { // faulted with exception Exception ex = t.Exception; while (ex is AggregateException && ex.InnerException != null) ex = ex.InnerException; MessageBox.Show("Error: " + ex.Message); } else if (t.IsCanceled) { // this should not happen // as you don''t pass a CancellationToken into your task MessageBox.Show("Canclled."); } else { // completed successfully MessageBox.Show("Result: " + t.Result); } }, TaskScheduler.FromCurrentSynchronizationContext()); }

Mientras se dirija a .NET 4.0 y desee el comportamiento de .NET 4.0 para las excepciones no observadas (es decir, vuelva a lanzar cuando la tarea se recolecte basura), debe configurarla explícitamente en la app.config :

<?xml version="1.0" encoding="utf-8"?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> <runtime> <ThrowUnobservedTaskExceptions enabled="true"/> </runtime> </configuration>

Mira esto para más detalles:

Excepciones de tareas no observadas en .NET4


try { var t1 = Task.Delay(1000); var t2 = t1.ContinueWith(t => { Console.WriteLine("task 2"); throw new Exception("task 2 error"); }, TaskContinuationOptions.OnlyOnRanToCompletion); var t3 = t2.ContinueWith(_ => { Console.WriteLine("task 3"); return Task.Delay(1000); }, TaskContinuationOptions.OnlyOnRanToCompletion).Unwrap(); // The key is to await for all tasks rather than just // the first or last task. await Task.WhenAll(t1, t2, t3); } catch (AggregateException aex) { aex.Flatten().Handle(ex => { // handle your exceptions here Console.WriteLine(ex.Message); return true; }); }