Dispatcher-Safe Observable Collection for WPF

wpf dispatcher safe

A common problem in WPF (& Silverlight) development is when you are working with multiple threads that need to change a collection that is a binding source and implements INotifyCollectionChanged.

Basically, the standard ObservableCollection will only allow updates from the dispatcher thread, which means you need to write a lot of code for the worker threads to marshal changes onto the main message pump via the dispatcher. This can be a bit tedious, so I recently wrote a collection that performs all of the necessary marshalling internally, so users of this type do not have to be concerned about thread affinity issues.

Also, I decided to use a ReaderWriterLock to provide thread-safety during updates to the collection.

Here is my collection class:

To test the effectiveness of this collection class, I wrote a simple WPF app, that bound to the new collection class and updated it via multiple threads:

And the code behind is below:

All my WPF app does is run a number of random actions against the collection from a variety of threads.

NOTE: When removing items from the collection I used the Refresh action of NotifyCollectionChangedAction instead of Remove. This is because the remove action doesnt work correctly in a multi-threaded scenario when used as a binding source for a list control in WPF.

If anyone has any siggestions or enhancements, please let me know.

The code for this article is on GitHub here-
https://github.com/deanchalk/DispatcherSafeObservableCollection

About the author

Dean Chalk

I am a freelance (contract) Microsoft WPF developer, specialising in challenging, high-performance user interface development. I have been working exclusively on enterprise WPF app development since 2006, and I have been a part of some of the most demanding WPF projects ever created withing the Investment Banking / trading industry.

  • Great one Dean – what a pitty that it does not work out of the box!
    To make it work, I adjusted the constructor to pass in the current dispatcher – otherwise I got the exception that the current dispatcher could not update the view.

    Thanks a bunch!
    Max


  • >