views:

4224

answers:

2

Hi,

I have a very bad feeling about using lock in my code but now the Dispatcher of WindowBase exists and I want to use it everywhere.

For example I use a multi thread singleton WCF service who publish events on the EventAggregator of PRISM, the payload is immutable (it is just data) and every thread with a dispatcher can retrieve the event gracefully, whitout deadlock in their own dispatcher. (Not only UI thread, but also threads with database calls, threads with services call, threads which log or other threads with slow calls, because I don't want to freeze the UI).

But my problem is that this Dispatcher is coupled with WPF so I feel a bit guilty when I use it everywhere, I feel that the dispatcher was not created for my use case in mind.

Does it exist another Dispatcher implementation not coupled with WPF ? or that's OK to abuse it ?

Thanks,

Update

The solution that Paul Stovell give to me is to create an interface IDispatcher, and an adapter for the Wpf Dispatcher, so this will be easier to test ! This solution was good for me because, I refactored my tests and I can now use a SynchronousDispatcherAdapter in my tests (Thanks to it, I don't have to use the Dispatcher of WPF in my tests).

Using the Dispatcher instead of a BackgroundWorker make sense, because I'm using a multi publisher / subscriber pattern (with PRISM), and thanks to the Dispatcher every event handler are called on threads who subscribe them to the event. This means that the only point where multi threading issue can happen is at the payload of my event (I made him immutable).

My different threads don't communicate directly between them they can just publish and subscribe to event. Thus, database calls, logs calls, services calls, UI calls run on different threads and don't know about each other (they only know about events they subscribe and publish).

The background worker will make sense, when I will make some calls from my UI to a repository.

But I hope to find a design without using BackgroundWorker because I prefere to use this subscriber/publisher pattern (I think it makes my code more readable)

+2  A: 

Hi, yes and no.. its a rendering thing..not a threading thing per se..

The Dispatcher selects work items on a priority basis and runs each one to completion. Every UI thread must have at least one Dispatcher, and each Dispatcher can execute work items in exactly one thread. as per this this link from Microsoft.

You still have to handle on your own any threads you start yourself.

Check this one for info on: Multithreaded Programming with the Event-based Asynchronous Pattern

Personally I use the Background Worker for my threading needs.

Best Practices here.

Ric Tokyo
BackgroundWorker use dispatcher because RunWorkerCompleted is called on the UI thread,so I think it's not so different than my solution.Using asynchronous event pattern you have to protect shared resources carefully with lock (I want to avoid this). With Dispatcher objects have their own thread.
Nicolas Dorier
Slashene, the dispatcher uses the same UI thread. It pushes itself onto the windows message pump the same way the background worker does, so it requires the same amount of locking as a background worker would.
Paul Stovell
The difference between the dispatcher and the BackgroundWorker, is that you can decide on which thread your code will execute. I just have to retrieve his Dispatcher. Whereas BackgroundWorker create a new thread and then complete on the dispatcher's thread which created the BackgroundWorker.
Nicolas Dorier
+8  A: 

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.

Paul Stovell
PRISM use IDispatcherFacade, and I have extended their class CompositePresentationEvent<T> and have add an overload to Subscribe :SubscriptionToken Subscribe(Action<T>, IDispatcherFacade, bool, Predicate<T>)So it is easy to test (the Wpf adapter is straightforward to code)
Nicolas Dorier
And you don't have to have a UI thread, because you can create a dispatcher on any thread using Dispatcher.Current
Nicolas Dorier
Ah ok sorry man, I forgot that when I use this interface with injection I am not anymore coupled with WPF thanks ;)
Nicolas Dorier