Перехват исключений из другого потока

У меня есть метод, работающий в отдельном потоке. Поток создается и запускается из формы в приложении 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);
        }
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
20 629
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Ответ принят как подходящий

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

Спасибо, никогда раньше не использовал Action <T>. Хорошее предложение.

Jeremy 10.10.2008 01:01

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

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

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

Другие вопросы по теме