Task Parallel Library and EventAggregator

Topics: Prism v4 - WPF 4
Jun 18, 2013 at 12:08 PM
Hi Everyone. I'm having issues using EventAggregator in a multi-threaded way.

I'm creating a partially connected application which synchronises databases. In the app I've got two View/ViewModels, one which displays the number of registered students on a dashboard and another which displays the list of students.

I've got a service which I've outlined roughly below. GetStudents ensures the databases are syncd and then returns the list, the other simply gets the count.

When Sync is successful it raises the SyncCompletedEvent.

The ShowCountView subscribes to this event and should re-count but because the event is raised from within a Task the binding in UI doesn't get updated because I'm on the wrong thread. Even if I invoke on Dispatcher.CurrentDispatcher it doesn't get executed on the UI thread, presumably because the CurrentDispatcher within the Task doesn't exist so a default one is created.

TL;DR; How do I update the UI using an Event raised within a Task?
public void GetStudents(Action<IEnumerable<Student>> callback)
{
    Task.Run(() => 
    {
          Sync();
          return students;
    }).ContinueWith(task =>
    {
          callback(task.Result);
    }, TaskScheduler.FromCurrentSynchronizationContext());
}
public void CountStudents(Action<int> callback)
{
    Task.Run(() => 
    {
        return students.Count();
    }).ContinueWith(task => 
    {
        callback(task.Result);
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

void Sync()
{
    // do sync
    _eventAggregator.GetEvent<SyncCompletedEvent>().Publish();
}
Developer
Jun 18, 2013 at 6:10 PM
Hi Ben,

When subscribing to an composite event using the EventAggregator you can specify in which thread you want to execute the "subscribed method" when the event is published; for example like this:
this.eventAggregator.GetEvent<MyEvent>().Subscribe(this.Method, ThreadOption.UIThread);
By default, the subscribed method is executed in the publisher's thread (in this case the Task's thread.) However, you should be able to change that so that it's executed in the UI thread passing ThreadOption.UIThread as an option during the subscription.

You can find more information about this in the following section of the documentation:
I hope this helps,

Damian Cherubini
http://blogs.southworks.net/dcherubini
Jun 18, 2013 at 6:19 PM
Hi Damian

Thanks for taking the time to reply. I actually discovered this overload this afternoon and hadn't had chance to reply myself yet. This has solved the problems I was having.

Thanks
Ben