2010-06-01 14 views
6

Come rilevare l'eccezione nel thread principale se l'eccezione si verifica nel thread secondario?Come rilevare l'eccezione nel thread principale se l'eccezione si verifica nel thread secondario?

Il frammento di codice per lo scenario è il seguente:

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

Non è possibile. Per uno, nel momento in cui viene lanciata l'eccezione, il try ... catch nel thread principale è già stato completato. –

risposta

3

È possibile aggiungere un gestore Application.ThreadException evento:

Joe è corretta. Date le finestre sopra inviate le schede codice stavo assumendo forme di Windows:

Questo evento consente al Windows Form applicazione per gestire altrimenti non gestite le eccezioni che si verificano in Windows Form thread. Collegare i gestori di eventi all'evento ThreadException per gestire queste eccezioni, che lasceranno l'applicazione in uno stato sconosciuto. Ove possibile, le eccezioni devono essere gestite da un blocco di gestione delle eccezioni strutturato .

Vedi Unexpected Errors in Managed Applications

+1

Penso che questa risposta sia sbagliata. AFAIK (ma non ho il tempo di testarlo), Application.ThreadException gestisce solo eccezioni dal thread dell'interfaccia utente (ad esempio un'eccezione non gestita in un gestore di eventi per un controllo WinForms). Le eccezioni dei thread di lavoro possono essere gestite da un gestore di eventi AppDomain.UnhandledException, ma il gestore verrà eseguito sul thread di lavoro, non sul thread principale dell'interfaccia utente. Se si desidera gestire le eccezioni da un thread di lavoro su un thread dell'interfaccia utente di WinForms, la soluzione migliore è utilizzare un oggetto BackgroundWorker come indicato nella risposta. – Joe

+0

che potrebbe essere il codice ASP.NET facilmente come Windows Form. Potrebbe persino essere pseudo-codice. –

+0

Vero. Attualmente sto lavorando a Winforms, quindi tutto sembra Winform! –

2

Utilizzare un BackgroundWorker.

Un BackgroundWorker fornisce l'infrastruttura per la comunicazione tra il thread principale dell'interfaccia utente e un thread di background worker, incluse le eccezioni di reporting. È quasi sempre una soluzione migliore rispetto all'avvio di un thread da un gestore di eventi button_click.

+0

"??????????" - Un BackgroundWorker fornisce l'infrastruttura per la comunicazione tra il thread principale dell'interfaccia utente e un thread di background worker, incluse le eccezioni di reporting. È quasi sempre una soluzione migliore rispetto all'avvio di un thread da un gestore di eventi button_click come nell'esempio dell'OP. – Joe

+2

sicuro ... quindi mettilo nella tua risposta :). Non che un riferimento sia negativo, ma una spiegazione è ancora meglio! – Kiril

0

È anche possibile utilizzare un delegato asincrono per presentare le informazioni se si è preoccupati di intercettare globalmente tutte le eccezioni.

vedi here

Vale a dire, intercettare l'eccezione del filo B e utilizzare il delegato asincrono all'informazione bolla fino a infilare A. In questo modo possono possono specificatamente destinazione quando i dati si gestisce l'eccezione.

0

Come ha detto @codeka, non è possibile. Ma se vuoi fare un po 'dell'interfaccia utente (può visualizzare un MessageBox di errore per l'utente) nel blocco catch nel thread secondario, puoi racchiudere in questo modo. Meglio se si utilizza BackgroundWorker

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

Si dovrebbe considerare di aggiungere il vostro gestione delle eccezioni nel metodo di prova e trattare con le eccezioni lì.

L'ebook gratuito Threading in C# discute questo approccio (e alcuni altri). Scorri verso il basso fino alla sezione "Gestione delle eccezioni".

0

È possibile (ora & hellip; questo non era disponibile quando la questione è stata originariamente chiesto) utilizzare async e await:

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

    } 
} 

Il metodo Task.Run() farà sì che il metodo Test() da eseguire in un thread di lavoro. Se viene generata un'eccezione non gestita in tale thread, Task propagherà tale eccezione al thread in attesa nell'istruzione await.

Problemi correlati