Когда вызывать SynchronizationContext.SetSynchronizationContext() в приложении пользовательского интерфейса?

Я узнаю о SynchronizationContext учебный класс. Я пытаюсь понять, каковы общие сценарии использования для вызова SynchronizationContext.SetSynchronizationContext() в контексте приложения WinForm/WPF. Что значит установить 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();

    });
}

2 ответа

Вы должны вообще оставить это до определенной библиотеки классов UI, чтобы установить это правильно. Winforms автоматически устанавливает экземпляр WindowsFormsSynchronizationContext, WPF устанавливает DispatcherSynchronizationContext, ASP.NET устанавливает AspNetSynchronizationContext, приложение Store устанавливает WinRTSynchronizationContext и так далее. Высокоспециализированные поставщики синхронизации, которые настроены на то, как поток пользовательского интерфейса отправляет события.

Есть что-то особенное в том, как эти прикладные среды используют свой основной поток. Все они реализуют диспетчерский цикл и используют потокобезопасную очередь для получения уведомлений. Обычно известный как "цикл сообщений" в программировании Windows GUI. Это общее решение проблемы производителя / потребителя, с циклом диспетчера, реализующим потребителя.

Создание собственного провайдера синхронизации для рабочего потока сначала требует, чтобы такой поток реализовывал тот же механизм. Другими словами, вам понадобится потокобезопасная очередь, такая как ConcurrentQueue, и поток должен быть записан для извлечения уведомлений из очереди и их выполнения. Объект делегата был бы хорошим выбором. Теперь у вас не возникнет проблем с реализацией метода Post, просто добавьте делегата SendOrPostCallback в очередь. Для реализации метода Send требуется дополнительная работа, поток должен сообщить, что делегат был получен и выполнен. Таким образом, объект очереди также нуждается в AutoResetEvent.

Обратите внимание, что ваш поток перестает становиться обычным полезным потоком, так как он вынужден отправлять эти уведомления. И как существующие поставщики синхронизации уже делают все это. Поэтому, если ваше приложение является приложением Winforms, вы можете также вызвать Application.Run() в своем рабочем потоке с фиктивной невидимой формой. И вы автоматически получите его провайдер синхронизации бесплатно.

В выпуске журнала MSDN Magazine за февраль 2011 года была статья о Google SynchronizationContexts и их различных реализациях во вселенной.NET.

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

Для меня это действительно помогло прояснить некоторую путаницу по этому вопросу. В целом, как говорит Ганс, в приложении WinForms/WPF вам не нужно и не следует использовать SetSynchronizationContext()

Другие вопросы по тегам