2011-04-06 11 views
5

J'ai entendu dire par une personne très perspicace qu'une exception étant lancée (et non interceptée) dans un thread est propagée au thread parent. Est-ce vrai? J'ai essayé quelque chose comme ça mais je n'ai pas pu attraper l'exception dans le thread de création.Exceptions dans une application multithread.

static void Main(string[] args) 
    { 
     ParameterizedThreadStart pts = 
      new ParameterizedThreadStart(ThreadMethod); 
     try 
     { 
      Thread t = new Thread(pts); 
      t.Start(new object()); 
      Console.ReadLine(); 
     } 
     catch (Exception ex) //the exception is not caught 
     { 
      Debugger.Break(); 
     } 
    } 


    static void ThreadMethod(object @object) 
    { 
     Thread.Sleep(2000); 
     throw new IndexOutOfRangeException(); 
     Thread.CurrentThread.Abort(); 
    } 
+0

Je suis sûr qu'il ne le jeter dans le fil il arrive, si vous voulez voir si une exception est pris utilisation http://msdn.microsoft.com/en-us/library/system. componentmodel.backgroundworker.runworkercompleted.aspx backgroundworker à la place –

Répondre

10

L'exception du thread ne se propagera pas au contexte du thread principal. Cela a vraiment du sens - au moment où l'exception est levée, le thread principal aura généralement une portée complètement différente de celle qui contient votre gestionnaire d'exception.

Vous pouvez intercepter ces exceptions (généralement pour les consigner) en les accrochant à AppDomain.UnhandledException. Voir cette page pour plus de détails, y compris les différences dans les applications Windows Forms, etc.

1

Non, ce n'est pas le cas. Pour attraper les exceptions de thread, vous devez utiliser Application.ThreadException.

1

Une ressource décente Threading en C# qui a une section pour la gestion des exceptions: Threading in C#

1

Exception vers le haut dans la propagation pile des appels.

Si vous démarrez un nouveau thread à partir d'une certaine méthode, il se propagera vers le haut jusqu'à ce qu'il arrive à cette méthode.

Si cette méthode ne l'attrape pas, vous obtiendrez une erreur d'exécution indiquant qu'il existe une exception non interceptée.

0

Voici une façon de l'attraper et manipuler de manière sûre:

BackgroundWorker bg = new BackgroundWorker(); 
object o; 
bg.DoWork += (c1,c2) => 
{   
     Thread.Sleep(2000);   
     throw new IndexOutOfRangeException(); 
}; 

bg.RunWorkerCompleted += (c3,c4) => 
{ 

if (((RunWorkerCompletedEventArgs)e).Error != null) 
    { 
     MessageBox.Show(((RunWorkerCompletedEventArgs)e).Error.Message); 
    } 
}; 
1

En bref, non, non. Vous avez deux options évidentes:. #

  1. LOGGUE dans la méthode de nouveaux départs de fil (haut de la pile pour le fil créé) dans
  2. Utilisez une construction comme délégué asynchrone, qui sera sera renvoie une exception lorsque vous appelez end end, que vous pouvez ensuite intercepter normalement.
1

Une exception ne peut être interceptée que sur le thread dont provient le message. Donc, lancer une exception sur un autre thread ne provoquera pas un autre thread à l'attraper.

Il n'y a pas de concept de thread "parent".

0

Il existe une solution très simple pour le cas particulier lorsque le thread principal attend l'achèvement de l'autre thread (voir https://msdn.microsoft.com/en-us/library/58195swd(v=vs.110).aspx#Examples). Il nécessite seulement une variable d'exception de classe.

L'exemple de code modifié complété par un gestionnaire d'exception peut ressembler à ceci.

using System; 
using System.Threading; 

class WaitOne 
{ 
    static AutoResetEvent autoEvent = new AutoResetEvent(false); 
    static Exception SavedException = null; 

    static void Main() 
    { 
     Console.WriteLine("Main starting."); 

     ThreadPool.QueueUserWorkItem(
      new WaitCallback(WorkMethod), autoEvent); 

     // Wait for work method to signal. 
     autoEvent.WaitOne(); 
     if (SavedException != null) 
     { 
      // handle this exception as you want 
     } 

     Console.WriteLine("Work method signaled.\nMain ending."); 
    } 

    static void WorkMethod(object stateInfo) 
    { 
     Console.WriteLine("Work starting."); 

     // Simulate time spent working. 
     try 
     { 
      Thread.Sleep(new Random().Next(100, 2000)); 
      throw new Exception("Test exception"); 
     } 
     catch (Exception ex) 
     { 
      SavedException = ex; 
     }    

     // Signal that work is finished. 
     Console.WriteLine("Work ending."); 
     ((AutoResetEvent)stateInfo).Set(); 
    } 
} 
Questions connexes