我有一个方法,在一个单独的线程中运行。线程创建并从Windows应用程序的形式启动。如果异常从螺纹内侧抛出,什么是以将其返回到主应用程序的最佳方式。现在,我传递一个参考到主窗体入线程,那么从线程调用方法,以及使由主应用程序线程调用的方法。是否有一个最佳实践方式,因为我不舒服,我怎么做,现在做到这一点。
我的窗体例子:
公共类frmMyForm:System.Windows.Forms.Form中
{
///<总结>
///创建一个线程
///< /总结>
///< PARAM NAME =发件人>< /参数>
///< PARAM NAME =E>< /参数>
私人无效btnTest_Click(对象发件人,EventArgs的)
{
尝试
{
//创建并启动线程
ThreadExample pThreadExample =新ThreadExample(本);
pThreadExample.Start();
}
赶上(例外前)
{
的MessageBox.show(ex.Message,Application.ProductName);
}
}
///<总结>
///从线程内部调用
///< /总结>
///< PARAM NAME =EX>< /参数>
公共无效的HandleError(例外前)
{
//在GUI的主线程调用一个方法
this.Invoke(新ThreadExample.delThreadSafeTriggerScript(的HandleError),新的对象[] {前});
}
私人无效__HandleError(例外前)
{
的MessageBox.show(ex.Message);
}
}
我的线程类的实例:
公共类ThreadExample
{
公共委托无效delThreadSafeHandleException(System.Exception的前);
私人螺纹thExample_m;
frmMyForm pForm_m;
私人frmMyForm表
{
得到
{
返回pForm_m;
}
}
公共ThreadExample(frmMyForm pForm)
{
pForm_m = pForm;
thExample_m =新主题(新的ThreadStart(主));
thExample_m.Name =示例主题;
}
公共无效启动()
{
thExample_m.Start();
}
私人无效的主要()
{
尝试
{
抛出新的异常(测试);
}
赶上(例外前)
{
Form.HandleException(前);
}
}
}
解决方案
让你在使用调用马歇尔回到UI线程,通过它的外观 - 这正是你需要做的。我个人用一个动作<异常>为简单起见,以及可能的BeginInvoke,而不是调用,但基本上你做了正确的事情
I have a method running in a seperate thread. The thread is created and started from a form in a windows application. If an exception is thrown from inside the thread, what is the best way to pass it back to the main application. Right now, I'm passing a reference to the main form into the thread, then invoking the method from the thread, and causing the method to be called by the main application thread. Is there a best practice way to do this because I'm not comfortable with how I'm doing it now.
Example of my form:
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);
}
}
Example of my thread class:
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);
}
}
}
解决方案
So you're using Invoke to marshall back to the UI thread, by the looks of it - which is exactly what you need to do. I'd personally use an Action<Exception> for simplicity's sake, and possibly BeginInvoke instead of Invoke, but basically you're doing the right thing.