2008-10-09 20 views
13

Ho un metodo in esecuzione in un thread separato. Il thread viene creato e avviato da un modulo in un'applicazione Windows. Se un'eccezione viene lanciata all'interno del thread, qual è il modo migliore per passarlo nuovamente all'applicazione principale. In questo momento sto passando un riferimento al form principale nel thread, quindi richiamando il metodo dal thread e facendo in modo che il metodo venga chiamato dal thread dell'applicazione principale. C'è un modo migliore di fare questo perché non sono a mio agio con come lo sto facendo ora.cattura eccezioni da un altro thread

Esempio della mia forma:

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); 
    } 
} 

esempio della mia classe thread:

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); 
     } 
    } 
} 

risposta

17

Quindi stai utilizzando Invoke per eseguire il marshall sul thread dell'interfaccia utente, a giudicare dall'aspetto, che è esattamente ciò che devi fare. Personalmente utilizzerei l'azione < Exception per semplicità e possibilmente BeginInvoke invece di Invoke, ma fondamentalmente stai facendo la cosa giusta.

+0

Grazie, non ho mai usato l'azione prima. Buon suggerimento – Jeremy

1

Lanciare eccezioni tra i thread non è facile e probabilmente non desiderato. invece è possibile passare l'eccezione utilizzando una struttura dati o una variabile condivisa e utilizzare waitHandle per attendere il 1 ° thread.

2

Probabilmente un modo migliore sarebbe passare un delegato nel thread anziché un riferimento al modulo stesso.

5

Utilizzare invece la classe BackgroundWorker nel framework .NET. È la procedura migliore per eseguire l'interfaccia utente su un thread diverso.

0

Sono assolutamente d'accordo con Dror. In modo formale possiamo chiamare questa struttura come FaultContract. Fondamentalmente quando un'eccezione si è verificata in un altro thread, il thread del client difficilmente può fare qualsiasi cosa in quel momento eccetto quello per raccogliere quell'informazione e agire di conseguenza nella sua stessa posizione. Se i theread sono in AppPool diversi, esiste una complessità extra di serializzazione (che può essere completamente un argomento separato).