Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的跨线程事件处理#_C#_Winforms_Multithreading_Event Handling - Fatal编程技术网

C# C语言中的跨线程事件处理#

C# C语言中的跨线程事件处理#,c#,winforms,multithreading,event-handling,C#,Winforms,Multithreading,Event Handling,我使用的框架在单独的线程中运行自己的事件调度器。框架可能会生成一些事件 class SomeDataSource { public event OnFrameworkEvent; void FrameworkCallback() { // This function runs on framework's thread. if (OnFrameworkEvent != null) OnFrameworkEvent(a

我使用的框架在单独的线程中运行自己的事件调度器。框架可能会生成一些事件

class SomeDataSource {

    public event OnFrameworkEvent;

    void FrameworkCallback() {

        // This function runs on framework's thread.

        if (OnFrameworkEvent != null)
            OnFrameworkEvent(args);
    }
}
我想将这些事件传递到Winforms线程上的Winforms对象。我显然会检查
invokererequired
,并在必要时将其发送到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
    ,那么如果表单关闭,调用是否仍会排队等待执行?(这意味着我仍然有机会遇到同样的问题)

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


  • 我没有将框架与自己的事件调度器一起使用,但我有自己创建线程的经验。这是我的经验

  • 这种方法不是线程安全的。即使程序本身已关闭,调用仍将被调用。我在任务管理器中看到这一点(正如您所说,程序关闭后)是挂起的线程。(即使您也从任务管理器中终止了程序。)。后来我不得不把这些线分开杀掉

  • 当窗体关闭时,您必须终止dispatcher线程,以便在该线程中发生任何错误时它不会挂起

    form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction;
     // pseudo-code (find c# equivalent)
    if (dispatcherthread.isrunning)
    dispatcherThread.kill();
    

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


    查看更多信息。

    您可以将此代码添加到构造函数
    CheckForIllegalCrossThreadCalls=false将不会引发异常。

    如果调度程序线程需要保持活动状态以处理其他Winforms,该怎么办?恐怕就是这样。我有多个窗体侦听同一事件源。如果我正确理解您的意思,那么将线程的IsBackground属性设置为true将防止挂起线程。我喜欢这种方法。我喜欢使用回调方法在线程完成时发出信号。