2008-10-09 2 views
13

У меня есть метод, выполняющийся в отдельном потоке. Поток создается и запускается из формы в приложении Windows. Если исключение выбрасывается из потока, то как лучше всего передать его в основное приложение. Прямо сейчас, я передаю ссылку на основную форму в поток, затем вызывая метод из потока и заставляя метод вызываться по основному потоку приложения. Есть ли лучший способ сделать это, потому что мне не нравится, как я это делаю сейчас.ловли исключений из другой темы

Пример моей формы:

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

Пример моего класса резьбы:

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

ответ

17

Итак, вы используете Invoke для перехода к потоку пользовательского интерфейса, по внешнему виду - именно это вам и нужно делать. Я бы лично использовал Action < Exception> для простоты и, возможно, BeginInvoke вместо Invoke, но в основном вы поступаете правильно.

+0

Спасибо, я никогда не использовал Action раньше. Хорошее предложение. – Jeremy

1

Бросив исключений между потоками не легко и, вероятно, не требуется. вместо этого вы можете передать исключение с использованием общей структуры данных или переменной и использовать waitHandle для ожидания в первом потоке.

2

Возможно, лучшим способом было бы передать делегат в поток вместо ссылки на форму.

5

Вместо этого используйте класс BackgroundWorker в платформе .NET. Это лучшая практика для выполнения пользовательского интерфейса в другом потоке.

0

Я полностью согласен с Dror. Формально мы можем назвать эту структуру как FaultContract. В принципе, когда в другом потоке произошло исключение, поток клиентов вряд ли может сделать что-то в тот момент, за исключением того, что собирать эту информацию и действовать соответственно в ней. Если они есть в разных AppPool, тогда существует дополнительная сложность Serialization (это может быть отдельная тема в целом).

Смежные вопросы