2010-06-01 23 views
6

Cómo detectar excepciones en el hilo principal si la excepción se produce en el hilo secundario?¿Cómo atrapar una excepción en el hilo principal si la excepción ocurre en el hilo secundario?

El fragmento de código para el escenario es la siguiente:

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     Thread th1 = new Thread(new ThreadStart(Test)); 
     th1.Start();    
    } 
    catch (Exception) 
    { 

    } 
} 

void Test() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(100); 

     if (i == 2) 
      throw new MyException(); 
    } 
} 
+0

No puede. Por un lado, en el momento en que se lanza la excepción, el try ... catch en el hilo principal ya se ha completado. –

Respuesta

3

Puede agregar un controlador Application.ThreadException Evento:

Joe es correcta. Dadas las ventanas anteriores formas de clave estaba asumiendo formas de Windows:

Este evento permite a Windows Forms aplicación para manejar de otra manera excepciones no controladas que se producen en Windows Forms hilos. Adjunte sus controladores de eventos al evento ThreadException para tratar estas excepciones, que dejarán su aplicación en en un estado desconocido. Siempre que sea posible, las excepciones deben manejarse mediante un bloque de manejo de excepciones estructurado .

Ver Unexpected Errors in Managed Applications

+1

Creo que esta respuesta es incorrecta. AFAIK (pero no tengo tiempo para probarlo), Application.ThreadException solo maneja las excepciones del subproceso UI (por ejemplo, una excepción no controlada en un controlador de eventos para un control WinForms). Las excepciones de los subprocesos de trabajo pueden manejarse mediante un controlador de evento AppDomain.UnhandledException, pero el controlador se ejecutará en el subproceso de trabajo, no en el subproceso principal de la UI. Si desea manejar excepciones de un subproceso de trabajador en un subproceso de interfaz de usuario de WinForms, la mejor solución es utilizar un BackgroundWorker como se indica en mi respuesta. – Joe

+0

que podría ser un código ASP.NET tan fácil como Windows Forms. Incluso podría ser un pseudocódigo. –

+0

Es cierto. Actualmente estoy trabajando en Winforms, ¡así que todo se ve como winforms! –

2

Utilice un BackgroundWorker.

Un BackgroundWorker proporciona la infraestructura para la comunicación entre el subproceso de interfaz de usuario principal y un subproceso de trabajo en segundo plano, incluidas las excepciones de informes. Casi siempre es una solución mejor que iniciar un hilo desde un controlador de evento button_click.

+0

"??????????" - Un BackgroundWorker proporciona la infraestructura para la comunicación entre el subproceso principal de la interfaz de usuario y un subproceso de trabajo en segundo plano, incluidas las excepciones de informes. Casi siempre es una mejor solución que iniciar un hilo desde un controlador de evento button_click como el ejemplo de OP. – Joe

+2

seguro ... así que ponlo en tu respuesta :). No es que una referencia sea mala, ¡pero una explicación es aún mejor! – Kiril

0

También puede utilizar un delegado asíncrono para crear la información si le preocupa capturar todas las excepciones de forma global.

ver here

Es decir, la trampa de la excepción en el subproceso B y utilizar el Delegado asíncrono a la información de la burbuja hasta enhebrar A. De esta manera se puede puede dirigirse específicamente cuando los datos de la excepción se maneja.

0

Como dijo @codeka, no se puede. Pero si desea hacer algunas cosas de UI (puede mostrar un MessageBox de error al usuario) en el bloque de captura en el hilo secundario, puede encerrar de esta manera. Mejor si se utiliza BackgroundWorker

Invoke(new Action(() => 
{ 
    MessageBox.Show("Message"); 
})); 
1

Usted debe considerar la adición de su manejo de excepciones en su método de prueba y tratar con excepciones allí.

El ebook gratuito Threading in C# analiza este enfoque (y algunos otros). Desplácese hasta la sección 'Manejo de excepciones'.

0

Usted puede (ahora y hellip; esto no estaba disponible cuando la pregunta fue hecha originalmente) utiliza async y await:

private async void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     await Task.Run(Test); 
    } 
    catch (Exception) 
    { 

    } 
} 

El método Task.Run() hará que el método Test() a ser ejecutado en un subproceso de trabajo. Si se lanza una excepción no controlada en ese subproceso, el Task propagará esa excepción nuevamente al subproceso en espera en la instrucción await.

Cuestiones relacionadas