WPF分派器是多线程问题的解决方案吗? [英] Is WPF Dispatcher the solution of multi threading problems?

查看:59
本文介绍了WPF分派器是多线程问题的解决方案吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对在代码中使用锁有一种很不好的感觉,但是现在WindowBase的Dispatcher存在了,我想在任何地方使用它.

例如,我使用一个多线程单例WCF服务,该服务在PRISM的EventAggregator上发布事件,有效载荷是不可变的(它只是数据),每个带有调度程序的线程都可以优雅地检索事件,而在自己的调度程序中避免死锁. (不仅UI线程,还有数据库调用的线程,服务调用的线程,日志记录的线程或慢速调用的其他线程,因为我不想冻结UI.)

但是我的问题是,此Dispatcher与WPF结合使用,因此当我在各处使用它时,我都会感到内feel,我觉得并不是为我的用例创建的.

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

谢谢

更新

Paul Stovell给我的解决方案是创建一个接口IDispatcher和一个Wpf Dispatcher适配器,因此这将更易于测试! 该解决方案对我来说是有好处的,因为我重构了测试,现在可以在测试中使用SynchronousDispatcherAdapter(感谢它,我不必在测试中使用WPF的Dispatcher).

使用Dispatcher代替BackgroundWorker是有意义的,因为我使用的是多发布者/订阅者模式(带有PRISM),并且由于Dispatcher的缘故,每个事件处理程序都在为其订阅事件的线程上被调用.这意味着可能发生多线程问题的唯一点是事件的有效负载(我使他不可变).

我的不同线程之间无法直接通信,它们只能发布和订阅事件. 因此,数据库调用,日志调用,服务调用,UI调用在不同的线程上运行,彼此之间不了解(它们仅了解它们订阅和发布的事件).

当我将一些从UI调用到存储库的调用时,后台工作器将很有意义.

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

解决方案

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

解决方案1 ​​

使用 SynchronizationContext .它具有在UI线程上调用的相同功能,并且可以在Windows或WPF中工作.测试它也可能.

解决方案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 的示例, href ="http://www.codeplex.com/bindablelinq/SourceControl/changeset/view/25046#293214" rel ="noreferrer"> WPF实现和 解决方案

The main issue with using the Dispatcher (or BackgroundWorker) is that it's difficult to test, unless your testing harness actually has a UI thread.

Solution 1

Use the SynchronizationContext. It provides the same ability to invoke on the UI thread and works in Windows or WPF. Testing it also possible.

Solution 2

Think of the dispatcher as being just another service. As you use PRISM, you are familiar with services and IOC. Here is how such a service may be used:

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

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

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

This allows you to substitute in different implementations for your platform/testing.

Here is an example of IDispatcher, a WPF implementation and a test implementation. You would register them with your IOC container just like any other service, and they are available to both UI and other services.

这篇关于WPF分派器是多线程问题的解决方案吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆