Tuesday, June 14, 2011

Concurrent Observable Collection, Dictionary, and Sorted Dictionary

Introduction
This article provides a description of how I implemented a Dictionary type class that can be bound to a WPF list control, but can be updated from a thread that is not the WPF user interface thread. This is useful for when you have worker threads updating a Dictionary and you want to have the contents of the Dictionary bound to a control. Microsoft does provide some ObservableCollection classes in .NET 4.0, but unfortunately ObservableDictionary isn't one of them, also the ObservableCollection classes they do provide aren't multi-threading friendly. While the classes I provide in this article aren't as efficient as the collections found in the new .NET 4.0 System.Collections.Concurrent namespace, they do allow worker threads to update an ordered collection bound to a view. There are some things in my implementation that I feel could be done better, so I welcome your comments, both positive and negative, at the bottom of this article.

Background
I wanted a Threadsafe Observable Sorted Dictionary, but before I got there I had to go through these steps:
Threadsafe Observable Collection
Observable Dictionary
Threadsafe Observable Dictionary
Observable Sorted Dictionary
Threadsafe Observable Sorted Dictionary


The Threadsafe Observable Collection
I started with the .NET framework ObservableCollection and set about making it threadsafe, keeping in mind the following things:
Prevent the collection being modified while a value is being read out
Prevent the collection being modified for the duration of external event handling
The collection is ordered, not a queue, so items need to be inserted
Need to be able to hand off an enumerable that, due to the collection's ordered nature, won't be affected by subsequent changes to the collection
What I came up with was a base class that uses a .NET ReaderWriterLock to control read and write access to an encapsulated ObservableCollection object, and iterates through all the event handlers and uses the dispatcher of any that are of DispatcherObject type to forward the collection changed events. To create an enumerable that won't be affected by subsequent changes, I just created a snapshot of the collection, so not the most elegant solution, but sufficient for my needs.

Read more: Codeproject