我有一个方法在一个单独的线程中运行。线程是从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);
}
}
}
因此,从外观上看,您正在使用Invoke编组回UI线程-这正是您需要做的。我个人会使用Action<为了简单起见,Exception>,可能是BeginInvoke而不是Invoke,但基本上你做的是正确的。
在中使用BackgroundWorker类。NET框架。这是在不同线程上执行UI工作的最佳实践。
可能更好的方法是将委托传递到线程中,而不是引用表单本身。
在线程之间引发异常并不容易,而且可能不是所希望的。相反,您可以使用共享数据结构或变量传递异常,并使用waitHandle在第一个线程上等待。
我完全同意Dror的观点。在形式上,我们可以将此结构称为FaultContract。从根本上说,当异常发生在另一个线程中时,客户端线程在那一刻几乎不能做任何事情,除了收集信息并在自己的线程中相应地采取行动。如果它们在不同的AppPool中,那么序列化就有额外的复杂性(这可能是一个单独的主题)。