wpf - WPF Dispatcher 是多线程问题的解决方案吗?

标签 wpf multithreading dispatcher

我对在我的代码中使用 lock 有一种非常不好的感觉,但是现在 WindowBase 的 Dispatcher 存在,我想在任何地方使用它。

例如,我使用一个多线程单例 WCF 服务,它在 PRISM 的 EventAggregator 上发布事件,有效负载是不可变的(它只是数据),并且每个带有调度程序的线程都可以优雅地检索事件,而不会在自己的调度程序中出现死锁。 (不仅是 UI 线程,还有数据库调用线程、服务调用线程、日志线程或其他调用慢的线程,因为我不想卡住 UI)。

但是我的问题是这个 Dispatcher 是与 WPF 耦合的,所以当我到处使用它时,我感到有点内疚,我觉得这个 Dispatcher 并不是为我的用例而创建的。

它是否存在另一个不与 WPF 耦合的 Dispatcher 实现?还是可以滥用它?

谢谢,

更新

Paul Stovell 给我的解决方案是创建一个接口(interface) IDispatcher,以及一个用于 Wpf Dispatcher 的适配器,这样会更容易测试!
这个解决方案对我有好处,因为我重构了我的测试,现在我可以在我的测试中使用 SynchronousDispatcherAdapter(多亏了它,我不必在我的测试中使用 WPF 的 Dispatcher)。

使用 Dispatcher 而不是 BackgroundWorker 是有意义的,因为我使用的是多发布者/订阅者模式(使用 PRISM),并且感谢 Dispatcher,每个事件处理程序都在订阅事件的线程上调用。这意味着多线程问题可能发生的唯一点是我的事件的有效负载(我让他不可变)。

我的不同线程之间不直接通信,它们只能发布和订阅事件。
因此,数据库调用、日志调用、服务调用、UI 调用在不同的线程上运行并且彼此不知道(它们只知道他们订阅和发布的事件)。

当我从我的 UI 对存储库进行一些调用时,后台工作人员将是有意义的。

但我希望找到一个不使用 BackgroundWorker 的设计,因为我更喜欢使用这种订阅者/发布者模式(我认为它使我的代码更具可读性)

最佳答案

使用 Dispatcher(或 BackgroundWorker)的主要问题是很难测试,除非您的测试工具实际上有一个 UI 线程。

解决方案 1

使用 SynchronizationContext .它提供了在 UI 线程上调用的相同能力,并在 Windows 或 WPF 中工作。测试它also possible .

解决方案 2

将调度程序视为另一种服务。当您使用 PRISM 时,您会熟悉服务和 IOC。以下是如何使用此类服务​​:

// 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 implementationtest implementation .您可以像任何其他服务一样将它们注册到您的 IOC 容器中,并且它们可用于 UI 和其他服务。

关于wpf - WPF Dispatcher 是多线程问题的解决方案吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/486758/

相关文章:

vb.net - .NET 创建新调度程序

wpf - 为什么偏爱 RelayCommand 而不是 RoutedCommand?

ios - GCD 串行线程执行流程

c - 是否可以用HI-TECH C为PIC12 MCU创建多线程程序

python - 如何从 Windows 上的线程内部更改 python 线程名称?

wpf - 如何获取 UI 线程 Dispatcher?

c# - 如何获取 SelectedItem 的所有子项

wpf - 在 wpf mvvm 数据绑定(bind)菜单项中添加额外级别

c# - 这真的是 WPF 的 SaveFileDialog.FileName 中需要的行为吗?

multithreading - 为什么在使用UI时线程会停止