C#中的跨线程事件处理

Ale*_*x B 11 c# multithreading event-handling winforms

我正在使用一个框架,该框架在一个单独的线程中运行自己的事件调度程序.框架可能会生成一些事件.

class SomeDataSource {

    public event OnFrameworkEvent;

    void FrameworkCallback() {

        // This function runs on framework's thread.

        if (OnFrameworkEvent != null)
            OnFrameworkEvent(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想将这些事件传递给Winforms线程上的Winforms对象.我显然检查InvokeRequired并在必要时将其发送到Winforms线程.

class SomeForm : Form {

    // ...

    public void SomeAction(SomeArgs args) {
        if (InvokeRequired) {
            BeginInvoke(new Action(SomeAction), args);
            return;
        }

        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

现在事件可能在表单处于关闭状态时传递,这会导致各种问题,因此我从Winforms线程上的框架事件源取消注册表单的事件处理程序,如下所示:

var form = new SomeForm();
var src = new SomeDataSource();

// ...

src.OnFrameworkEvent += form.SomeAction;
form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction;
Run Code Online (Sandbox Code Playgroud)
  1. 现在,这种方法是线程安全的吗?如果表单处于关闭状态,并且外部线程调用BeginInvoke,那么如果表单关闭,调用是否仍会排队等待执行?(这意味着我仍然有机会遇到同样的问题)

  2. 是否有更好的方法或推荐的跨线程事件处理模式?

Han*_*ant 4

不它不是。当您取消注册线程并关闭表单时,该线程可能只是在执行事件处理程序。几率很小,但不是零。您必须先停止线程,然后才能关闭表单。如果您不想中止它,则必须通过取消 FormClosing 事件来保持表单打开,然后让线程的完成回调关闭表单。

检查此线程以获取更多信息。