I was wondering, if it is safe to bind a WPF control to a concurrent collection, specifically a wrapper class around one of the System.Collections.Concurrent
collections that also implements INotifyCollectionChanged
?
I understand that CollectionChanged
must be invoked on the UI-thread (and without the index parameters). But, what happens, if another thread manipulates the source collection while the UI is updating itself? Does WPF just gracefully ignore the problem (like it does in so many other places)?
That depends on the implementation of your wrapper. Let's make a simple example adding INotifyCollectionChanged
to a BlockingCollection<T>
allowing calls of non UI threads:
public void AddNotified(T item)
{
base.Add(item);
var args = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
item,
Count - 1);
//Ensure no items are changed until the UI is updated
Application.Current.Dispatcher.Invoke(() =>
CollectionChanged?.Invoke(this, args));
}
The implementation of Add
itself is threadsafe, but to be sure the UI shows the current items the implementation you need to ensure that there are no other items are changed between adding and updating (See comment in code).
WPF updates the UI based on the NotifyCollectionChangedAction
and updated items passed at raising the INotifyCollectionChanged.CollectionChanged
. This means the UI relys on this information. The result: An interim collection update leads to an unsynchronized UI until the update was raised or a NotifyCollectionChangedAction.Reset
was called and the UI shows different items like inside your source collection.
Synchronizing collections with the UI is a very wide and intresting topic. There are already multiple solutions available that may match your specific problem. To give you some possible approaches to solve problems like this have a look at here are some links: