WPF Cross-Thread Collection Binding – Part 2 – Property Change Events
Update: The final solution has been posted.
As it turns out, I was not the first to design a simple, lock-free, cross-thread collection binding solution. Beatriz Costa’s InvokeOC<T> class works too, and she did it in 2006. Her article can be found here. In her sample she uses locks to simulate using it from multiple threads, but what I did not realize during my research is that it will work perfectly without locks from a single worker thread (provided the UI thread does not modify the collection). Thanks Josh Smith for making me revisit her sample. Her design consists of a single collection deriving from ObservableCollection, overriding the collection change methods, and enforcing that the collection is synchronously updated on the UI thread. Here is example code that shows an overridden method:
protected override void InsertItem(int index, T item)
{
if (dispatcherUIThread.CheckAccess())
{
base.InsertItem(index, item);
}
else
{
dispatcherUIThread.Invoke(DispatcherPriority.Send,
new InsertItemCallback(InsertItem), index, new object[] { item });
}
}
By using ‘Invoke’ the worker thread will block until the UI updates the collection. This blocking ensures that both the worker and UI thread will be reading the most up to date copy at the same time, therefore both threads can read the collection at the same time. However, without locks it is not thread-safe, so you can only modify the collection from one worker thread. She also includes another class called BeginInvokeOC<T>, but it is not reliable so do not use it under any circumstance.
At this point there are two solutions for cross thread collection binding to a collection on a single worker thread:
-InvokeOC<T>: A blocking single collection
-ObservableBackgroundList<T>: A non-blocking double collection
Property Change Notification from Worker Threads
I mentioned in the previous article that I was going to address the issue of potentially flooding the UI thread with notifications. After some research into the solution I decided that the added complexity was not worth the gain and I may revisit the scenario another time. Instead, I want to move on to the guts of the issues at hand for cross thread collection binding.
Developers that bind to a collection from a separate thread will almost certainly bind to properties on the objects in the collection. A percentage of these developers will then want to change some of these properties from the worker thread. Unfortunately, this is not supported out of the box in .NET 3.5 and 3.0 SP1 (I am not sure about .NET 3.0). The reason has to do with the way WPF listens for property and collection change events. In short it is believed that the lack of support is because the static event manager that is handling the change events is not properly synchronized when property changes come from a worker thread. Here is another diagram to illustrate what happens when collection and property change events are raised:

Since the ‘Event Manager’ is static, it is inherently shared between any thread that accesses it. And since collection change events are required to come from the UI thread but property change events are not, the two events can conflict with each other when a property change occurs from a worker thread. An exception that can result from this conflict is:
“Unable to cast object of type ‘System.Collections.Specialized.HybridDictionary’ to type ‘ListenerList’.”
All hope is not lost, since Part 3 will include a solution to get around this problem.