我正在使用一个在单独的线程中运行自己的事件调度程序的框架。该框架可能会生成一些事件。
class SomeDataSource {
public event OnFrameworkEvent;
void FrameworkCallback() {
// This function runs on framework's thread.
if (OnFrameworkEvent != null)
OnFrameworkEvent(args);
}
}
我想将这些事件传递给 Winforms 线程上的 Winforms 对象。我显然检查了 InvokeRequired
并在必要时将其分派(dispatch)给 Winforms 线程。
class SomeForm : Form {
// ...
public void SomeAction(SomeArgs args) {
if (InvokeRequired) {
BeginInvoke(new Action(SomeAction), args);
return;
}
// ...
}
}
现在,当表单处于关闭过程中时可能会传递事件,这会导致各种问题,因此我在 Winforms 线程上从框架的事件源中注销了表单的事件处理程序,如下所示:
var form = new SomeForm();
var src = new SomeDataSource();
// ...
src.OnFrameworkEvent += form.SomeAction;
form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction;
现在,这种方法是线程安全的吗?如果窗体正在关闭过程中,并且外部线程调用了
BeginInvoke
,调用是否会如果表单关闭,是否仍要排队等待执行? (这意味着我仍然有机会遇到同样的问题)是否有更好的跨线程事件处理方法或推荐模式?
最佳答案
不,不是。当您取消注册并关闭表单时,线程可能只是在执行事件处理程序。赔率很小,但不是零。您必须先停止线程,然后才能关闭表单。如果您不想中止它,则必须通过取消 FormClosing 事件使表单保持打开状态,然后让线程的完成回调关闭表单。
检查 this thread了解更多信息。
关于c# - C#中的跨线程事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2159176/