C#多线程 - 无控件调用

col*_*ium 17 c# multithreading invoke

我对多线程有点熟悉,因为我已经读过它,但从未在实践中使用它.

我有一个项目使用第三方库,通过引发事件来共享输入设备的状态.问题是,编写库的方式这些事件是从不同的线程引发的.

我的应用程序不需要是多线程的,我遇到了很多经典的线程问题(UI控件抱怨从不同的线程进行交互,集合会被修改为一段代码迭代它,等等).

我只想将第三方库的事件返回给我的UI线程.具体我认为应该发生的是:

我的类接收事件,处理程序正在与UI不同的线程上运行.我想检测这种情况(比如使用InvokeRequired),然后执行BeginInvoke的等效操作以将控制权交还给UI线程.然后可以在类层次结构上发送正确的通知,并且只有一个线程触及我的所有数据.

问题是,接收这些输入事件的类不是从Control派生的,因此没有InvokeRequired或BeginInvoke.原因是我试图干净地分离UI和底层逻辑.该类仍然在UI线程上运行,它在类本身内部没有任何UI.

现在我通过破坏这种分离来解决问题.我传入一个引用控件,该控件将显示来自我的类​​并使用 Invoke方法的数据.这似乎违背了分离它们的整个目的,因为现在底层类直接依赖于我的特定UI类.

也许有一种方法可以保存对运行构造函数的线程的引用,然后在Threading命名空间中会有一些执行Invoke命令的东西?

有没有解决的办法?我的方法完全错了吗?

小智 18

看看AsyncOperation课程.您可以AsyncOperation使用该AsyncOperationManager.CreateOperation方法在要调用处理程序的线程上创建实例.我使用的参数Create通常为null,但您可以将其设置为任何值.要在该线程上调用方法,请使用该AsyncOperation.Post方法.


ang*_*son 13

使用SynchronizationContext.Current,它将指向您可以与之同步的内容.

根据应用类型,这将做正确的事情.对于WinForms应用程序,它将在主UI线程上运行它.

具体来说,使用SynchronizationContext.Send方法,如下所示:

SynchronizationContext context =
    SynchronizationContext.Current ?? new SynchronizationContext();

context.Send(s =>
    {
        // your code here
    }, null);
Run Code Online (Sandbox Code Playgroud)

  • +1.请注意,如果程序是控制台应用程序,则"SynchronizationContext.Current"为null.一个好的模式是使用`AsyncOperation`,它在创建时捕获当前的`SynchronizationContext`,*做正确的事情++*™.http://msdn.microsoft.com/en-us/library/system.componentmodel.asyncoperation.aspx (7认同)