Pregunta

Tengo una pequeña aplicación WinForms que utiliza un objeto BackgroundWorker para realizar una operación de larga duración.

La operación en segundo plano arroja excepciones ocasionales, generalmente cuando alguien tiene un archivo abierto que se está recreando.

Independientemente de si el código se ejecuta desde el IDE o no .NET muestra un cuadro de diálogo de error que informa al usuario que se ha producido una excepción no controlada. Compilar el código usando la configuración de Release tampoco cambia esto.

Según MSDN :

  

Si la operación genera una excepción que su código no maneja, BackgroundWorker captura la excepción y la pasa al controlador de eventos RunWorkerCompleted, donde se expone como la propiedad Error de System.ComponentModel .. ::. RunWorkerCompletedEventArgs. Si está ejecutando el depurador de Visual Studio, el depurador se interrumpirá en el punto del controlador de eventos DoWork donde se produjo la excepción no controlada.

Espero que estas excepciones se produzcan ocasionalmente y me gustaría manejarlas en el evento RunWorkerCompleted en lugar de en DoWork. Mi código funciona correctamente y el error se maneja correctamente dentro del evento RunWorkerCompleted, pero por mi vida no puedo descubrir cómo detener el diálogo de error .NET quejándose de & Quot; Excepción no controlada & Quot; de ocurrir.

¿No se supone que BackgroundWorker detecta ese error automáticamente? ¿No es eso lo que dice la documentación de MSDN? ¿Qué debo hacer para informar a .NET de que este error se está manejando y al mismo tiempo permitir que la excepción se propague a la propiedad Error de RunWorkerCompletedEventArgs?

¿Fue útil?

Solución

Lo que estás describiendo no es el comportamiento definido de BackgroundWorker. Estás haciendo algo mal, sospecho.

Aquí hay una pequeña muestra que demuestra que BackgroundWorker come excepciones en DoWork y las pone a su disposición en RunWorkerCompleted :

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        if(e.Error != null)
        {
            MessageBox.Show("There was an error! " + e.Error.ToString());
        }
    };
worker.RunWorkerAsync();

Mis habilidades de depuración psíquica me revelan su problema: está accediendo a e.Result en su controlador RunWorkerCompleted; si hay un e.Error, debe manejarlo sin acceder a e.Result. Por ejemplo, el siguiente código es malo, malo, malo y generará una excepción en tiempo de ejecución:

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        // OH NOOOOOOOES! Runtime exception, you can't access e.Result if there's an
        // error. You can check for errors using e.Error.
        var result = e.Result; 
    };
worker.RunWorkerAsync();

Aquí hay una implementación adecuada del controlador de eventos RunWorkerCompleted:

private void RunWorkerCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
       DoSomethingWith(e.Result); // Access e.Result only if no error occurred.
    }
}

VOILA, no recibirá excepciones de tiempo de ejecución.

Otros consejos

Agregaría al texto de MSDN :

  

Si la operación genera una excepción que su código no maneja, BackgroundWorker captura la excepción y la pasa al controlador de eventos RunWorkerCompleted, donde se expone como la propiedad Error de System.ComponentModel .. ::. RunWorkerCompletedEventArgs. Si está ejecutando el depurador de Visual Studio, el depurador se interrumpirá en el punto del controlador de eventos DoWork donde se produjo la excepción no controlada.

... Y el depurador informará la excepción como " ~ La excepción no fue manejada por el código de usuario "

Solución: No se ejecute bajo el depurador y funciona como se esperaba: Excepción atrapada en e.Error.

Esta es una vieja pregunta, pero la encontré mientras buscaba en Google los mismos síntomas. Publicar esto en caso de que alguien más lo encuentre por el mismo motivo.

La respuesta de Judá es correcta, pero no es la única razón por la & "; excepción no controlada en el código de usuario &"; cuadro de diálogo puede aparecer. Si se lanza una excepción desde el interior de un constructor en el subproceso de fondo, esa excepción provocará el diálogo inmediatamente y no se pasará al evento RunWorkerCompleted. Si mueve el código infractor fuera de cualquier constructor (a cualquier otro método) funciona como se esperaba.

[Editar]

Judá tiene un gran punto. Mi ejemplo señaló los detalles específicos para manejar el error, pero mi código en realidad causaría otra excepción si nunca se golpeó una excepción en el método DoWork. Este ejemplo está bien debido al hecho de que estamos mostrando específicamente las capacidades de manejo de errores de BackgroundWorker. Sin embargo, si no está comprobando el parámetro de error contra nulo, este podría ser su problema.

[/ Editar]

No veo los mismos resultados. ¿Puedes publicar un pequeño código? Aquí está mi código.

private void Form1_Load(object sender, EventArgs e)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.RunWorkerAsync();
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Will cause another exception if an exception didn't occur.
    // We should be checking to see if e.Error is not "null".
    textBox1.Text = "Error? " + e.Error;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i < 10; i++)
    {
        if (i < 5)
        {
            Thread.Sleep(100);
        }
        else
        {
            throw new Exception("BOOM");
        }   
    }
}

Salida del programa:

  

¿Error? System.Exception: BOOM en   BackgroundException.Form1.worker_DoWork (Object   remitente, DoWorkEventArgs e) en   D: \ Workspaces \ Sandbox \ BackgroundException \ BackgroundException \ Form1.cs: línea   43 en   System.ComponentModel.BackgroundWorker.OnDoWork (DoWorkEventArgs   comer   System.ComponentModel.BackgroundWorker.WorkerThreadStart (Object   argumento)

Un artículo interesante que se parece a tu pregunta. Tiene una sección sobre manejo de excepciones.

http://www.developerdotstar.com/community/node/671

Tuve el mismo problema y ya estaba aplicando la respuesta de Judá antes de encontrar este tema después de buscar en Google.

Bueno, la respuesta de Judá es parcialmente correcta. Encontré una mejor respuesta aquí

El depurador está haciendo el trabajo bien, si ejecuta la aplicación en " condiciones del mundo real " ;, el RunWorkerCompleted trata con la excepción como se esperaba y el comportamiento de la aplicación también es el esperado.

Espero que esta respuesta ayude.

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