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

2024-01-02

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

Edit:

@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 线程调度事件的方式进行调整。

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

何时在 UI 应用程序中调用 SynchronizationContext.SetSynchronizationContext()? 的相关文章

随机推荐