Когда вызывать 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();

    });
}

person Sylvain    schedule 11.01.2011    source источник


Ответы (2)


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

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

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

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

person Hans Passant    schedule 11.01.2011
comment
мое обновление меняет ваш ответ? Как вы думаете, следует ли также избегать установки SynchronizationContext в рабочем потоке? - person Sylvain; 12.01.2011
comment
Мне бы очень хотелось услышать, что вы думаете об этом... Спасибо. - person Sylvain; 14.01.2011
comment
Ганс, не могли бы вы помочь мне с stackoverflow.com/questions/13500030/ - я нашел Мне пришлось использовать SetSync, потому что в моем классе он не устанавливался функцией «Отправить/Почта». - person tofutim; 21.11.2012

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

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

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

person Yoopergeek    schedule 11.08.2011