WPF分派器是多线程问题的解决方案吗? [英] Is WPF Dispatcher the solution of multi threading problems?
问题描述
我对在代码中使用锁有一种很不好的感觉,但是现在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屋!