перехват исключений из другого потока - PullRequest
13 голосов
/ 10 октября 2008

У меня есть метод, запущенный в отдельном потоке. Поток создается и запускается из формы в приложении 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);
        }
    }
}

Ответы [ 5 ]

17 голосов
/ 10 октября 2008

Таким образом, вы используете Invoke для маршалинга обратно в поток пользовательского интерфейса, что выглядит именно так, и это именно то, что вам нужно сделать. Я бы лично использовал Действие для простоты и, возможно, BeginInvoke вместо Invoke, но в основном вы делаете правильные вещи.

5 голосов
/ 21 октября 2008

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

2 голосов
/ 10 октября 2008

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

1 голос
/ 10 октября 2008

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

0 голосов
/ 16 августа 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...