Является ли диспетчер WPF решением проблем с несколькими потоками?
У меня очень плохое чувство об использовании блокировки в моем коде, но теперь Диспетчер WindowBase существует, и я хочу использовать его везде.
Например, я использую многопользовательскую службу singleton WCF, которая публикует события в EventAggregator PRISM, полезная нагрузка неизменна (это всего лишь данные), и каждый поток с диспетчером может изящно извлекать событие, независимо от тупика в своем диспетчере, (Не только поток пользовательского интерфейса, но также потоки с вызовами базы данных, потоки с вызовом служб, потоки, которые регистрируются или другие потоки с медленными вызовами, потому что я не хочу замораживать пользовательский интерфейс).
Но моя проблема заключается в том, что этот диспетчер связан с WPF, поэтому я чувствую себя немного виноватым, когда использую его везде, я чувствую, что диспетчер не был создан для моего использования.
Существует ли еще одна реализация диспетчера, не связанная с WPF? или что ОК, чтобы злоупотреблять им?
Спасибо,
Обновление
Решение, которое Пол Стовелл дает мне, это создать интерфейс IDispatcher и адаптер для диспетчера Wpf, так что это будет легче протестировать!
Это решение было полезно для меня, потому что я реорганизовал свои тесты, и теперь я могу использовать SynchronousDispatcherAdapter в своих тестах (благодаря этому мне не нужно использовать диспетчер WPF в моих тестах).
Использование диспетчера вместо BackgroundWorker имеет смысл, потому что я использую шаблон нескольких издателей/подписчиков (с PRISM), и благодаря диспетчеру каждый обработчик событий вызывается в потоках, которые подписывают их на событие. Это означает, что единственная точка, в которой может возникнуть проблема с несколькими потоками, - это полезная нагрузка моего события (я сделал его неизменным).
Мои разные потоки не связываются напрямую между ними, они могут просто публиковать и подписываться на событие.
Таким образом, вызовы базы данных, вызовы журналов, вызовы служб, вызовы пользовательского интерфейса выполняются на разных потоках и не знают друг о друге (они знают только о событиях, которые они подписывают и публикуют).
Фоновый работник будет иметь смысл, когда я сделаю некоторые вызовы из моего интерфейса в репозиторий.
Но я надеюсь найти дизайн без использования BackgroundWorker, потому что я предпочитаю использовать этот шаблон подписчика/издателя (я думаю, что он делает мой код более удобочитаемым)
Ответы
Ответ 1
Основная проблема с использованием диспетчера (или 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
да и нет.. его вещь для рендеринга... ничтожная вещь сама по себе..
Диспетчер выбирает рабочие элементы в приоритетном порядке и запускает каждый из них до завершения. В каждом потоке пользовательского интерфейса должен быть хотя бы один диспетчер, и каждый диспетчер может выполнять рабочие элементы только в одном потоке. в соответствии с этим эта ссылка от Microsoft.
Вам все равно придется самостоятельно обрабатывать любые темы, которые вы начинаете сами.
Отметьте этот для получения информации о: Многопоточное программирование с асинхронным шаблоном на основе событий
Лично я использую Background Worker для моих потребностей в потоке.
Лучшие практики здесь.