c# - 何时在 UI 应用程序中调用 SynchronizationContext.SetSynchronizationContext()?

标签 c# wpf winforms multithreading synchronizationcontext

我正在学习 SynchronizationContext 类。我试图了解在 WinForm/WPF 应用程序的上下文中调用 SynchronizationContext.SetSynchronizationContext() 的常见使用场景是什么。设置线程的SynchronizationContext 是什么意思?我应该什么时候做,为什么?另外,如果我设置了它,我应该在某个时候取消设置吗?

编辑:

在他的回答中,@Hans Passant 问我为什么要考虑 SetSynchronizationContext()。我的想法是在工作线程上设置上下文,以便在该线程上运行的代码可以使用上下文。

private void button3_Click(object sender, EventArgs e)
{
    var syncContext = SynchronizationContext.Current;
    Task.Factory.StartNew(() =>
    {
        // Setup the SynchronizationContext on this thread so 
        // that SomeAsyncComponentThatNeedsACurrentContext
        // will have a context when it needs one
        if (SynchronizationContext.Current == null)
            SynchronizationContext.SetSynchronizationContext(syncContext);

        var c = new SomeAsyncComponentThatNeedsACurrentContext();
        c.DoSomething();

    });
}

最佳答案

您通常应该将其留给特定的 UI 类库来正确设置。 Winforms 自动安装 WindowsFormsSynchronizationContext 实例,WPF 安装 DispatcherSynchronizationContext,ASP.NET 安装 AspNetSynchronizationContext,Store 应用程序安装 WinRTSynchronizationContext,等等。高度特定的同步提供程序,已根据 UI 线程分派(dispatch)事件的方式进行调整。

这些应用程序环境使用主线程的方式有些特别。它们都实现了调度程序循环并使用线程安全队列来接收通知。在 Windows GUI 编程中通常称为“消息循环”。这是生产者/消费者问题的通用解决方案,其中调度程序循环实现了消费者。

首先为工作线程创建您自己的同步提供程序需要这样的线程实现相同的机制。换句话说,您将需要一个线程安全的队列,如 ConcurrentQueue,并且需要编写线程以从队列中检索通知并执行它们。委托(delegate)对象将是一个不错的选择。您现在可以毫无问题地实现 Post 方法,只需将 SendOrPostCallback 委托(delegate)添加到队列中即可。需要额外的工作来实现 Send 方法,线程需要发回信号表明委托(delegate)已被检索和执行。所以队列对象也需要一个 AutoResetEvent。

请注意您的线程现在如何停止成为一个普遍有用的线程,它因必须分派(dispatch)这些通知而陷入困境。以及现有的同步提供程序如何完成所有这些工作。因此,如果您的应用程序是 Winforms 应用程序,那么您也可以使用虚拟不可见表单在您的工作线程上调用 Application.Run()。您将自动免费获得其同步提供程序。

关于c# - 何时在 UI 应用程序中调用 SynchronizationContext.SetSynchronizationContext()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4658819/

相关文章:

c# - 如何禁用 Telerik GridView 行中的特定单元格

c# - PrintTicket 提供程序无法绑定(bind)到打印机。 Win32错误: The printer name is invalid

c# - 计算 TabControl 中 Tab 的宽度(Windows 窗体)

c# - Winforms - 调整 CheckedListBox 上垂直滚动条的宽度

c# - Unity3D XML(-RPC) 和 C#

c# - 具有足够精度以实现计算器的数字类型

c# - 单元测试 Azure System.IO.FileLoadException : Could not load file or assembly 'System.Text.Json'

c# - 如何绑定(bind)到 View 中但不在 View 模型中的属性?

c# - 如何将 Windows 窗体设计器生成的组合框放入数组中

c# - 这个 `if` 语句是否会产生空引用异常?