2010-06-01 3 views
6

Comment intercepter l'exception dans le thread principal si l'exception se produit dans le thread secondaire?Comment intercepter l'exception dans le thread principal si l'exception se produit dans le thread secondaire?

L'extrait de code pour le scénario est donné ci-dessous:

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

Vous ne pouvez pas. Pour un, au moment où l'exception est levée, le try ... catch dans le thread principal est déjà terminé. –

Répondre

3

Vous pouvez ajouter un Application.ThreadException gestionnaire de l'événement:

Joe est correct. Étant donné les fenêtres ci-dessus forme de code que je supposais Windows Forms:

Cet événement permet à votre application Windows Forms pour gérer autrement exceptions non gérées qui se produisent dans threads Windows Forms. Attachez vos gestionnaires d'événements à l'événement ThreadException pour gérer ces exceptions, , ce qui laissera votre application dans un état inconnu. Si possible, les exceptions doivent être gérées par un bloc de gestion des exceptions structuré .

Voir Unexpected Errors in Managed Applications

+1

Je pense que cette réponse est fausse. AFAIK (mais je n'ai pas le temps de le tester), Application.ThreadException ne gère que les exceptions du thread UI (par exemple, une exception non gérée dans un gestionnaire d'événement pour un contrôle WinForms). Les exceptions des threads de travail peuvent être gérées par un gestionnaire d'événement AppDomain.UnhandledException, mais le gestionnaire s'exécutera sur le thread de travail, pas sur le thread principal de l'interface utilisateur. Si vous souhaitez gérer les exceptions d'un thread de travail sur un thread d'interface utilisateur WinForms, la meilleure solution consiste à utiliser un BackgroundWorker comme indiqué dans ma réponse. – Joe

+0

qui pourrait être du code ASP.NET aussi facilement que Windows Forms. Ce pourrait même être du pseudo-code. –

+0

True. Je travaille actuellement sur Winforms, donc tout ressemble à des winforms! –

2

Utilisez un BackgroundWorker. BackgroundWorker fournit l'infrastructure de communication entre le thread principal de l'interface utilisateur et un thread de travail en arrière-plan, y compris les exceptions de génération de rapports. C'est presque toujours une meilleure solution que de démarrer un thread à partir d'un gestionnaire d'événement button_click.

+0

"??????????" - Un BackgroundWorker fournit l'infrastructure de communication entre le thread principal de l'interface utilisateur et un thread de travail en arrière-plan, y compris les exceptions de génération de rapports. C'est presque toujours une meilleure solution que de démarrer un thread à partir d'un gestionnaire d'événements button_click comme l'exemple de l'OP. – Joe

+2

sûr ... alors mettez-le dans votre réponse :). Pas qu'une référence est mauvaise, mais une explication est encore meilleure! – Kiril

0

Vous pouvez également utiliser un délégué asynchrone pour faire monter en flèche les informations si vous souhaitez récupérer globalement toutes les exceptions.

voir here

Autrement dit, l'exception piège à fil B et utiliser le Délégué Async à l'information de bulles jusqu'à enfiler A. De cette façon, on peut cibler spécifiquement lorsque les données de l'exception est gérée.

0

Comme l'a dit @codeka, vous ne pouvez pas. Mais si vous voulez faire des choses d'interface utilisateur (peut afficher une erreur MessageBox à l'utilisateur) dans le bloc catch dans le thread secondaire, vous pouvez placer comme ceci. Mieux, si vous utilisez BackgroundWorker

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

Vous devriez envisager d'ajouter votre traitement d'exception dans votre méthode d'essai et de traiter les exceptions là.

Le livre gratuit Threading in C# traite de cette approche (et d'autres). Faites défiler jusqu'à la section «Gestion des exceptions».

0

Vous pouvez (maintenant & hellip; ce n'était pas disponible lorsque la question a été posée) utiliser async et await:

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

    } 
} 

La méthode Task.Run() provoquera la méthode Test() à exécuter dans un thread de travail. Si une exception non gérée est levée dans ce thread, le Task propagera cette exception au thread en attente à l'instruction await.

Questions connexes