2008-10-09 4 views
13

J'ai une méthode qui s'exécute dans un thread séparé. Le thread est créé et démarré à partir d'un formulaire dans une application Windows. Si une exception est générée à l'intérieur du thread, quel est le meilleur moyen de le renvoyer à l'application principale. À l'heure actuelle, je passe une référence au formulaire principal dans le thread, puis j'appelle la méthode du thread et la méthode est appelée par le thread d'application principal. Y a-t-il une façon de faire les meilleures pratiques parce que je ne suis pas à l'aise avec la façon dont je le fais maintenant.intercepter des exceptions d'un autre thread

Exemple de ma forme:

public class frmMyForm : System.Windows.Forms.Form 
{ 
    /// <summary> 
    /// Create a thread 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void btnTest_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      //Create and start the thread 
      ThreadExample pThreadExample = new ThreadExample(this); 
      pThreadExample.Start(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, Application.ProductName); 
     } 
    } 

    /// <summary> 
    /// Called from inside the thread 
    /// </summary> 
    /// <param name="ex"></param> 
    public void HandleError(Exception ex) 
    { 
     //Invoke a method in the GUI's main thread 
     this.Invoke(new ThreadExample.delThreadSafeTriggerScript(HandleError), new Object[] { ex }); 
    } 

    private void __HandleError(Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

Exemple de ma classe de fil:

public class ThreadExample 
{ 
    public delegate void delThreadSafeHandleException(System.Exception ex); 

    private Thread thExample_m; 

    frmMyForm pForm_m; 
    private frmMyForm Form 
    { 
     get 
     { 
      return pForm_m; 
     } 
    } 

    public ThreadExample(frmMyForm pForm) 
    { 
     pForm_m = pForm; 

     thExample_m = new Thread(new ThreadStart(Main)); 
     thExample_m.Name = "Example Thread"; 
    } 

    public void Start() 
    { 
     thExample_m.Start(); 
    } 

    private void Main() 
    { 
     try 
     { 
      throw new Exception("Test"); 
     } 
     catch (Exception ex) 
     { 
      Form.HandleException(ex); 
     } 
    } 
} 

Répondre

17

Ainsi, vous utilisez Invoke pour revenir à la thread d'interface utilisateur, par son apparence - ce qui est exactement ce que vous devez faire. J'utiliserais personnellement une Exception d'Action < pour des raisons de simplicité, et peut-être BeginInvoke au lieu d'Invoke, mais en fait, vous faites la bonne chose.

+0

Merci, je n'ai jamais utilisé l'action auparavant. Bonne suggestion. – Jeremy

1

Lancer exceptions entre les threads est pas facile et probablement pas souhaité. à la place, vous pouvez passer l'exception en utilisant une structure de données ou une variable partagée et utiliser waitHandle pour attendre le 1er thread.

2

Probablement un meilleur moyen serait de passer un délégué dans le thread au lieu d'une référence au formulaire lui-même.

5

Utilisez plutôt la classe BackgroundWorker dans le framework .NET. C'est la meilleure pratique pour effectuer un travail d'interface utilisateur sur un thread différent.

0

Je suis totalement d'accord avec Dror. De manière formelle, nous pouvons appeler cette structure FaultContract. Fondamentalement, lorsqu'une exception s'est produite dans un autre thread, le thread client peut difficilement faire n'importe quoi à ce moment sauf pour collecter cette information et agir en conséquence dans son propre intérêt. Si les thereads sont dans AppPool différent alors il y a une complexité supplémentaire de Serialization (qui peut être un sujet séparé complètement).

Questions connexes