简体   繁体   English

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

[英]When to call SynchronizationContext.SetSynchronizationContext() in a UI application?

I'm learning about the SynchronizationContext class. 我正在学习SynchronizationContext类。 I'm trying to understand what are the common usage scenarios for calling SynchronizationContext.SetSynchronizationContext() in the context of a WinForm/WPF application. 我试图了解在WinForm / WPF应用程序的上下文中调用SynchronizationContext.SetSynchronizationContext()的常见用法场景。 What does it mean to set the SynchronizationContext of a thread? 设置线程的SynchronizationContext意味着什么? When should I do it and why? 我什么时候该做,为什么? Also, if I set it, should I unset it at some point? 另外,如果我设置它,我应该在某个时候取消它吗?

Edit: 编辑:

In his answer, @Hans Passant asked why I was contemplating SetSynchronizationContext() . 在他的回答中,@ Hans Passant问我为什么要考虑SetSynchronizationContext() The idea I have is to set the context on a worker thread so that code running on that thread will have a context to use. 我的想法是在工作线程上设置上下文,以便在该线程上运行的代码将具有要使用的上下文。

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();

    });
}

You should in general leave it up to the specific UI class library to set this correctly. 您通常应该将其留给特定的UI类库来正确设置它。 Winforms automatically installs a WindowsFormsSynchronizationContext instance, WPF installs a DispatcherSynchronizationContext, ASP.NET installs a AspNetSynchronizationContext, a Store app installs WinRTSynchronizationContext, etcetera. Winforms自动安装WindowsFormsSynchronizationContext实例,WPF安装DispatcherSynchronizationContext,ASP.NET安装AspNetSynchronizationContext,Store应用程序安装WinRTSynchronizationContext等。 Highly specific synchronization providers that are tuned to the way the UI thread dispatches events. 高度特定的同步提供程序,它们调整为UI线程调度事件的方式。

There's something special about the way these application environments use their main thread. 这些应用程序环境使用主线程的方式有一些特别之处。 They all implement a dispatcher loop and use a thread-safe queue to receive notifications. 它们都实现了一个调度程序循环,并使用一个线程安全的队列来接收通知。 Generally known as the "message loop" in Windows GUI programming. 通常称为Windows GUI编程中的“消息循环”。 This is a generic solution to the producer/consumer problem, with the dispatcher loop implementing the consumer. 这是生产者/消费者问题的通用解决方案,调度程序循环实现了消费者。

Creating your own synchronization provider for a worker thread first requires that such a thread implements this same mechanism. 为工作线程创建自己的同步提供程序首先要求这样的线程实现相同的机制。 In other words, you will need a thread-safe queue, like ConcurrentQueue, and the thread needs to be written to retrieve notifications from the queue and execute them. 换句话说,您将需要一个线程安全的队列,如ConcurrentQueue,并且需要编写线程以从队列中检索通知并执行它们。 A delegate object would be a good choice. 委托对象将是一个不错的选择。 You will now have no problem implementing the Post method, simply add the SendOrPostCallback delegate to the queue. 现在,您将实现Post方法没有问题,只需将SendOrPostCallback委托添加到队列即可。 Extra work is required to implement the Send method, the thread needs to signal back that the delegate was retrieved and executed. 实现Send方法需要额外的工作,线程需要发回信号表示检索并执行了委托。 So the queue object also needs an AutoResetEvent. 所以队列对象也需要一个AutoResetEvent。

Do note how your thread now stops becoming a generally useful thread, it is bogged down by having to dispatch these notifications. 请注意您的线程现在如何停止成为一个通常有用的线程,它必须通过发送这些通知而陷入困境。 And how the existing synchronization providers already do all of this. 现有的同步提供商如何完成所有这些工作。 So if your app is a Winforms app then you might as well call Application.Run() on your worker thread with a dummy invisible form. 因此,如果您的应用程序是Winforms应用程序,那么您也可以使用虚拟不可见形式在工作线程上调用Application.Run()。 And you'll automatically get its synchronization provider for free. 并且您将自动免费获得其同步提供程序。

The February 2011 issue of MSDN Magazine had a google article discussion SynchronizationContexts and their various implementations across the .NET universe. 2011年2月的MSDN杂志有一篇谷歌文章讨论了SynchronizationContexts及其在.NET领域的各种实现。

http://msdn.microsoft.com/en-us/magazine/gg598924.aspx http://msdn.microsoft.com/en-us/magazine/gg598924.aspx

For me, it really helped clear up some of the confusion over the issue. 对我来说,这确实有助于消除对这个问题的一些困惑。 In general, as Hans says, in a WinForms/WPF application, you don't need to, and shouldn't, use SetSynchronizationContext() 一般来说,正如汉斯所说,在WinForms / WPF应用程序中,您不需要也不应该使用SetSynchronizationContext()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SynchronizationContext.Post到UI方法 - SynchronizationContext.Post to UI Method 从另一个线程调用方法而不会阻塞该线程(或为非UI线程编写自定义SynchronizationContext)C# - call method from another thread without blocking the thread (or write custom SynchronizationContext for non-UI thread) C# 如何附加非UI线程的SynchronizationContext - How to attach SynchronizationContext of Non-UI thread 创建SynchronizationContext时的异常做法? - Exception practices when creating a SynchronizationContext? 使用await时不流动SynchronizationContext - SynchronizationContext is not flowed when using await WPF / WCF异步服务调用和SynchronizationContext - WPF/WCF Async Service Call and SynchronizationContext SynchronizationContext.Send调用Func返回结果 - SynchronizationContext.Send to call a Func returning a result SynchronizationContext,它何时流动,何时不流动? - SynchronizationContext, when does it flow and when does it not? 在不同项目中时,将SynchronizationContext传递给ViewModel - Pass SynchronizationContext to ViewModel when it's in a different projects 使用SynchronizationContext时async / await死锁 - async/await deadlocking when using a SynchronizationContext
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM