Является ли WPF Dispatcher решением проблем с многопоточностью? - PullRequest
19 голосов
/ 28 января 2009

У меня очень плохое предчувствие использования блокировки в моем коде, но теперь существует Диспетчер WindowBase, и я хочу использовать его везде.

Например, я использую многопоточный одноэлементный WCF-сервис, который публикует события в EventAggregator PRISM, полезная нагрузка является неизменной (это просто данные), и каждый поток с диспетчером может извлекать событие изящно, без тупика в своем собственном диспетчере. , (Не только поток пользовательского интерфейса, но также потоки с вызовами базы данных, потоки с вызовом служб, потоки, которые регистрируют или другие потоки с медленными вызовами, потому что я не хочу замораживать пользовательский интерфейс).

Но моя проблема в том, что этот Диспетчер связан с WPF, поэтому я чувствую себя немного виноватым, когда использую его везде, и чувствую, что диспетчер не был создан для моего случая использования.

Существует ли другая реализация Dispatcher, не связанная с WPF? или это нормально злоупотреблять этим?

Спасибо

Обновление

Решение, которое мне дал Пол Стовелл, состоит в том, чтобы создать интерфейс IDispatcher и адаптер для Wpf Dispatcher, так что это будет легче протестировать! Это решение мне пригодилось, потому что я реорганизовал свои тесты и теперь могу использовать SynchronousDispatcherAdapter в своих тестах (благодаря этому мне не нужно использовать Dispatcher of WPF в моих тестах).

Использование Dispatcher вместо BackgroundWorker имеет смысл, потому что я использую шаблон с несколькими издателями / подписчиками (с PRISM), и благодаря Dispatcher каждый обработчик событий вызывается в потоках, которые подписывают их на событие. Это означает, что единственная точка, в которой может возникнуть проблема с многопоточностью, - это полезная нагрузка моего события (я сделал его неизменным).

Мои разные темы не общаются напрямую между собой, они могут просто публиковать и подписываться на событие. Таким образом, вызовы базы данных, журналы вызовов, вызовы служб, вызовы пользовательского интерфейса выполняются в разных потоках и не знают друг о друге (они знают только о событиях, которые они подписывают и публикуют).

Фоновый рабочий будет иметь смысл, когда я сделаю несколько звонков из своего пользовательского интерфейса в хранилище.

Но я надеюсь найти дизайн без использования BackgroundWorker, потому что я предпочитаю использовать этот шаблон подписчик / издатель (я думаю, что это делает мой код более читабельным)

Ответы [ 2 ]

16 голосов
/ 28 января 2009

Основная проблема с использованием Dispatcher (или BackgroundWorker) заключается в том, что его сложно тестировать, если только у вашего жгута тестирования нет потока пользовательского интерфейса.

Раствор 1

Используйте SynchronizationContext . Он обеспечивает такую ​​же возможность вызова в потоке пользовательского интерфейса и работает в Windows или WPF. Тестирование также возможно .

Решение 2

Думайте о диспетчере как о другой службе. Поскольку вы используете PRISM, вы знакомы с услугами и МОК. Вот как можно использовать такую ​​услугу:

// Not a UI component
public class MyDomainService : IMyDomainService
{
   private readonly IDispatcher _dispatcher;

   public MyDomainService(IDispatcher dispatcher) 
   {
      _dispatcher = dispatcher;
   }

   private void GotResultFromBackgroundThread()
   {
       _dispatcher.Dispatch(() => DoStuffOnForegroundThread());
   }
}

Это позволяет вам заменить платформу / тестирование в различных реализациях.

Вот пример IDispatcher , реализация WPF и реализация теста . Вы должны зарегистрировать их в своем контейнере IOC, как и любой другой сервис, и они доступны как для пользовательского интерфейса, так и для других сервисов.

2 голосов
/ 28 января 2009

да и нет .. это вещь рендеринга .. а не многопоточность сама по себе ..

Диспетчер выбирает рабочие элементы в приоритетном порядке и запускает каждый из них до завершения. В каждом потоке пользовательского интерфейса должен быть хотя бы один диспетчер, и каждый диспетчер может выполнять рабочие элементы ровно в одном потоке. согласно этой этой ссылке от Microsoft.

Вам все равно придется самостоятельно обрабатывать любые темы, которые вы запускаете.

Проверьте этот для получения информации о: Многопоточное программирование с асинхронным шаблоном на основе событий

Лично я использую Background Worker для своих потребностей в потоках.

Лучшие практики здесь .

...