2

读过“当前 SynchronizationContext 是当前线程的属性”正确的短语后,我有点困惑......

在 VS2010 的 C# 应用程序代码中,当我键入时,我Thread.CurrentThread.在 Intellisense 给出的选项下拉列表中找不到线程的任何上下文相关属性。

我知道当前的同步上下文可以通过 " = SynchronizationContext.Current;" 获得。但这对于在并行线程、任务等中同时执行并不是很幸运。

假设从控制台或 WPF (*)应用程序中,我在其自己的主 UI 线程以及 TPL 任务 中创建并启动了一些 Windows 窗体。

我认为每个winform都应该有自己的WindowsFormaSynchronizationContext,WPF 应该有自己的DispatcherSynchronizationContextSynchronizationContext 类的子类)实例,任务在具有自己的同步上下文的ThreadPool中执行, LongRunning 任务或者可能会在其线程池中执行自己的同步上下文...

那么,为什么不能SynchronizationContext从线程中定义呢?“从给定线程获取 SynchronizationContext”问题的所有答案似乎都在否定这种可能性......

最后但并非最不重要的一点是:“当前 SynchronizationContext 是当前线程的属性”
这句话是否正确? 那么,我如何才能为不同的特定线程实例获取此属性的值?

(*)
最近,我收到了基本上使用 winforms 的 C# WPF 应用程序代码。

4

1 回答 1

8

这是准确的。SynchronizationContext.Current 属性使用当前线程的 m_ExecutionContext 字段。这是 Thread 类的私有字段,这就是您在 IntelliSense 下拉列表中看不到它的原因。

它以这种方式工作很重要,默认的 SynchronizationContext 不会同步任何内容。它的 Post() 方法目标在线程池线程上运行。将目标调用编组到特定线程是一件非常重要的事情。这需要目标线程的帮助,它需要为生产者-消费者问题提供解决方案。通用解决方案是从线程安全队列中检索消息的循环。与 Winforms 或 WPF 应用程序的 UI 线程的工作方式完全相同,它们“泵送消息循环”。Application.Run() 启动该循环。

因此,只有此类应用程序的 UI 线程可以支持不使用线程池线程运行 Post() 委托目标的同步提供程序。因此,Winforms 和 WPF 在您创建窗体或窗口后立即安装它们自己的同步提供程序。只有在 UI 线程上运行的代码才能从 SynchronizationContext.Current 属性中看到该非默认提供程序。

结果是您必须在 UI 线程上初始化需要编组回调到 UI 线程的代码。因此,例如必须在 UI 线程上创建 BackgroundWorker。或者使用 TaskScheduler.FromCurrentSynchronizationContext 创建的任务。从技术上讲,可以有多个线程显示 UI,无论 init 代码运行在哪个线程上都会确定 Post() 委托目标将在何处运行。这可能解释了您的问题,如果您的 init 代码在工作线程上运行,则 Post() 目标在线程池线程上运行。您可以将对 Synchronization.Current 对象的引用传递给工作线程,只要您在 UI 线程上获得了该引用。

于 2013-04-30T11:51:21.943 回答