2012-07-04 3 views
2

Je veux attraper une exception dans un thread A, puis passer l'objet exception à un thread B, et le jeter du thread B. Est-ce sûr?Sûr de lancer une exception créée sur un autre thread C#

Discussion A

try { 
    // Code that throws exceptions 
} catch (Exception e) { 
    sendToOtherThread(e); 
} 

Discussion B

Exception e = receiveException(); 
throw e; 

EDIT

Par souci de clarté: Je comprends comment fonctionne le filetage, et comment je passerais la référence d'objet d'un fil à l'autre. La question est plus à propos est-il sûr de jeter un objet d'exception d'un thread qui ne l'a pas créé ou y at-il un problème avec la classe Exception lui-même ou la façon dont .NET le gère.

+0

Oui mais (peut être) assez inutile parce que vous ne pouvez pas réémettre si vous écraserez stacktrace d'origine. Si ce n'est pas ce que vous voulez, vous devez envelopper l'exception et lancer la nouvelle. –

+0

Je suis très curieux de votre implémentation de 'sendToOtherThread' et' receiveException'. –

+0

Disons simplement que ces deux méthodes transmettent la référence de l'objet telle quelle. Donc e dans les deux threads se réfèrent au même objet. –

Répondre

1

Vous peut réémettre une exception reçue d'un autre fil (par exemple, dans un gestionnaire d'événements RunWorkerCompleted de BackgroundWorker), mais il serait plus habituel de l'envelopper dans une autre exception, pour préserver la pile trace:

private void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e) 
{ 
    // First, handle the case where an exception was thrown. 
    if (e.Error != null) 
    { 
     throw new SomeException("... message ...", e.Error); 
    } 
    ... 
} 
0

Vous aurez besoin de changer ceci:

dans cette discussion B

Exception e = receiveException(); 
throw new Exception("Write something here, for example: 'Received from other thread'", e); // so you keep the stack trace 

Mais je regarderais pour des mises en garde (je ne suis pas tout à fait sûr que ce soit 100% sûr).

+0

Merci pour la suggestion de rembobinage. Mais la question est toujours sans réponse: -/ –

+0

C'est une bonne idée d'envelopper votre exception pour garder une trace du fil d'origine qui jette l'exception, mais comme OP a dit, ce n'est pas une réponse à la question – AaA

0

Il doit être sûr, mais la plupart probablement mettra fin à fil B.

Votre solution ne dépend que de la façon dont vous passez votre objet d'exception de la discussion A à B. fil si vous mettez dans une ressource partagée vous devez verrouiller et libérer cette ressource partagée spécifique. A part ça, il n'y a rien de dangereux sur votre code.

Tant que vous n'accédez à aucune ressource partagée dans les threads, tout le reste devrait être sûr.

0

Exception est une classe et donc un type de référence standard, si vous voulez le passer entre threads (ce qui sonne un peu étrange) vous devez vous assurer que personne d'autre ne tente de modifier l'instance (surtout si vous créez mutable types d'exception).

Solution A
Vous pouvez faire un pull-modèle producteur-consommateur

BlockingCollection<Exception> bc = new BlockingCollection<Exception>(); 

// thread A - Producer 
try 
{ 
    ... 
} 
catch(Exception ex) 
{ 
    bc.Add(ex); 
} 


//thread B - Consumer 
try 
{ 
    // Consume bc 
    while (true) 
    { 
     var ex = bc.Take(); 
     //thread sleep 
    } 
} 
catch (InvalidOperationException) 
{ 
    // IOE means that Take() 
    // was called on a completed collection and no 
    // No more exceptions, restart checking  
} 

Solution B
Mais sans doute une meilleure idée serait de ne pas utiliser modèle de traction, comme dans ce cas, il peut gaspiller des ressources, mais plutôt pousser-modèle avec des collections observables thread safe.

1

Si vous envisagez d'utiliser .NET 4.0, toutes les exceptions générées par Task sont automatiquement propagées au thread parent lorsque le Task est joint. C'est par conception et devrait être parfaitement sûr.Jetez un coup d'oeil ici: http://msdn.microsoft.com/en-us/library/dd997415.aspx

+0

Merci votre réponse est bonne aussi mais je ne peux voter que pour un –

Questions connexes