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





Выбрасывать исключения между потоками непросто и, вероятно, нежелательно. вместо этого вы можете передать исключение, используя общую структуру данных или переменную, и использовать waitHandle для ожидания первого потока.
Итак, вы, судя по всему, используете Invoke для маршалинга обратно в поток пользовательского интерфейса - это именно то, что вам нужно сделать. Я лично для простоты использовал бы Action <Exception> и, возможно, BeginInvoke вместо Invoke, но в основном вы делаете правильные вещи.
Вероятно, лучшим способом было бы передать делегата в поток вместо ссылки на саму форму.
Вместо этого используйте класс BackgroundWorker в платформе .NET. Это лучший способ выполнять работу пользовательского интерфейса в другом потоке.
Я полностью согласен с Дрором. Формально мы можем назвать эту структуру FaultContract. По сути, когда исключение произошло в другом потоке, клиентский поток вряд ли может что-либо сделать в этот момент, кроме сбора этой информации и соответствующих действий в своем собственном потоке. Если тэды находятся в разных пулах приложений, тогда существует дополнительная сложность сериализации (это может быть отдельной темой).
Спасибо, никогда раньше не использовал Action <T>. Хорошее предложение.