2010-02-20 22 views
8

En una aplicación WPF tengo una tarea de acceso a la base de datos supervisada, ejecutada periódicamente por un temporizador y esta tarea se ha ejecutado en un subproceso BackgroundWorker.¿Cómo manejar excepciones desde un subproceso BackgroundWorker?

Cuando falló el intento de conexión, planteé una excepción mediante la construcción try_catch y deseo actualizar un texto de la barra de estado en una secuencia de UI.

¿Hay alguna construcción evento prebuild en un BackgroundWorker para implementar esto, algo así como DoWorkEventHandler o RunWorkerCompletedEventHandler, que se puede utilizar para esto? Si no, ¿cómo hacerlo mejor?

Editado (añadió):

Si quiero manejar la excepción dentro RunWorkerCompletedEventHandler, utilizando e.Error parámetro, no funciona. En caso dejo excepción no controlada en el hilo BackgroundWorker, la aplicación se cuelga en puntos y depurador a la cadena de código que está en el interior excuted BackgroundWorker hilo, diciendo que: excepción fue controlada por el código de usuario.

Por lo tanto, en este caso, el hilo no se detiene, indicando a RunWorkerCompletedEventHandler que se detuvo con un error, pero toda la aplicación deja de funcionar.

+0

Gracias a todos por responder! Tomando en cuenta algunas respuestas, actualicé mi pregunta con más detalles. – rem

Respuesta

5

A WPF UI se puede actualizar desde un subproceso de fondo mediante el uso de Dispatcher.BeginInvoke.

Por ejemplo, si su código de fondo era parte de una ventana entonces se podría actualizar un TextBlock:

this.Dispatcher.BeginInvoke((Action)(() => 
    { 
     textBlock.Text = "Connection Failed!"; 
    })); 

Editar:

Si el código de fondo se encontraban en una clase que no sea su ventana se podría hacer una interfaz para ayudar:

public interface IShowStatus 
{ 
    void ShowStatus(string message); 
} 

implementar la interfaz en la ventana de

public void ShowStatus(string message) 
{ 
    this.Dispatcher.BeginInvoke((Action)(() => 
     { 
      textBlock.Text = message; 
     })); 
} 

En su clase con el trabajador de fondo haga una propiedad para mantener una referencia a la interfaz.

public IShowStatus StatusDisplay { get; set; } 

En su clase de Windows, inicialice la clase de fondo.

public void InitBackground() 
{ 
    BackgroundClass background = new BackgroundClass(); 
    background.StatusDisplay = this; 
    ... 

último en su subproceso de fondo se puede decir:

StatusDisplay.ShowStatus("Connection Failed!"); 
+0

En mi caso, el código de fondo no es parte de una ventana, pero se ejecuta dentro de una clase separada. Además, la excepción tiene lugar en un método estático. Entonces, ESTA palabra clave no es válida en este caso. Por favor, ayúdame a entender, ¿cómo podría hacer referencia a mi ventana principal de IU en este caso? – rem

+0

Agregué notas en respuesta a su pregunta. –

6

El RunWorkerCompletedEventArgs e del RunWorkerCompletedEventHandler contiene la propiedad Error es del tipo Excepción. Si no se produjo ninguna excepción durante el trabajo del hilo de fondo, el prpery tiene valor nulo. De lo contrario, contiene el error que ocurrió.

3
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Exception exceptionThrowDuringDoWorkEventHandler = e.Error; 
} 
+0

Cuando intento lanzar una excepción desde el subproceso BackgroundWorker, la aplicación simplemente se bloquea con: Exception no fue manejada por el código de usuario. Nunca llegué a bw_RunWorkerCompleted. ¿Me estoy perdiendo de algo? – Doug

3

Ajuste el WorkerReportsProgress propiedad del trabajador de fondo para cierto, a continuación, agregar un controlador de eventos para el evento ProgressChanged.En el siguiente código, agregué un controlador de eventos para Form.Load también.

Ahora pruebe el siguiente código:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      MessageBox.Show(e.UserState.ToString()); 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       //some code that throws an exception 
       throw new NotImplementedException(); 
      } 
      catch (Exception ex) 
      { 
       backgroundWorker1.ReportProgress(0/*percent of progress*/, ex); 

      } 
     } 
     private void Form1_Load(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 
Cuestiones relacionadas