从给定的线程获取SynchronizationContext

chi*_*oro 7 c# multithreading .net-3.5 synchronizationcontext

我似乎没有找到如何获得SynchronizationContext给定的Thread:

Thread uiThread = UIConfiguration.UIThread;
SynchronizationContext context = uiThread.Huh?;
Run Code Online (Sandbox Code Playgroud)

我为什么需要那个?

因为我需要从前端应用程序的不同位置发布到UIThread.所以我在一个名为的类中定义了一个静态属性UIConfiguration.我在Program.Main方法中设置了这个属性:

UIConfiguration.UIThread = Thread.CurrentThread;
Run Code Online (Sandbox Code Playgroud)

在那一刻我可以肯定我有正确的线程,但是我不能设置像这样的静态属性

UIConfiguration.SynchronizationContext = SynchronizationContext.Current
Run Code Online (Sandbox Code Playgroud)

因为尚未安装该类的WinForms实现.由于每个线程都有自己的SynchronizationContext,因此必须可以从给定Thread对象中检索它,或者我完全错了?

Ree*_*sey 13

这是不可能的.问题是a SynchronizationContext和a Thread实际上是两个完全独立的概念.

虽然Windows Forms和WPF都SynchronizationContext为主线程设置了一个,但大多数其他线程都没有.例如,ThreadPool中没有任何线程包含自己的SynchronizationContext(当然,除非您自己安装).

它也有可能为SynchronizationContext完全无关的线程和线程.可以轻松设置同步上下文,该同步上下文与外部服务或整个线程池等同步.

在您的情况下,我建议您UIConfiguration.SynchronizationContext在初始主表单的Loaded事件中进行设置.保证在该点开始上下文,并且在任何情况下消息泵启动之前将无法使用.


Jav*_*t93 7

我知道这是一个老问题,并为necro道歉,但我刚刚找到了解决这个问题的方法,我认为这对我们这些一直在谷歌搜索的人来说可能是有用的(并且它不需要一个Control实例).

基本上,您可以创建WindowsFormsSynchronizationContext的实例并在Main函数中手动设置上下文,如下所示:

    _UISyncContext = new WindowsFormsSynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(_UISyncContext);
Run Code Online (Sandbox Code Playgroud)

我在我的应用程序中完成了这项工作,它完美无缺.但是,我应该指出我Main的标有STAThread,所以我不确定这是否仍然Main有用(或者如果它甚至是必要的话),如果你的标记为MTAThread.

编辑:我忘记提及它,但_UISyncContextProgram在我的应用程序中的类中的模块级别定义.


Gen*_*нин 6

从Alex Davies的书“ C#5.0中的Async。O'Reilly Publ。,2012”,第48-49页中,我发现以下几段内容对我来说最简洁,最有用:

  • 的SynchronizationContext是.NET Framework提供的一类,它具有在运行代码的能力,特定类型的线程
    有各种同步上下文使用.NET,其中最重要的是通过WinForms和使用的UI线程上下文WPF。”

  • SynchronizationContext本身的实例并没有做任何非常有用的事情,因此它的所有实际实例都倾向于是子类。

    它还具有静态成员,可让您读取和控制当前成员SynchronizationContext

    当前SynchronizationContext是当前线程的属性。

    这个想法是,在您运行在特殊线程中的任何时候,您都应该能够获取SynchronizationContext并存储电流。以后,您可以使用它在开始的特殊线程上运行代码。所有这一切都应该是可能的,而无需确切地知道您从哪个线程开始,只要您可以使用SynchronizationContext,就可以返回它

    SynchronizationContext的重要方法是Post,它可以使委托在正确的上下文中运行”

  • 有些SynchronizationContexts封装了一个线程,例如UI线程
    有些封装了一种特定类型的线程(例如,线程池),但是可以选择其中的任何线程来将委托发布到其中。有些实际上并没有更改该线程中的哪个线程。代码在上面运行,但仅用于监视,例如ASP.NET同步上下文”