Here is the seventh (OMG !) post on the WPF 4.5 new features. Collections are a part of every application and their management is maybe the first thing you learn to deal with in WPF.
To begin, you put everything on the main(the UI one) thread and it works just fine. After a few time, you realize that it freezes the application UI and that the users usually don’t like it. Then you put the collections creation/feeding on another Thread to free the UI’s one and you realize that it is not possible because : “This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread”.
In this post we will discover that this is over with WPF 4.5 (and that you’ll love it) !
How do we do in WPF 4.0 ?
Let’s say that you have an application which display peoples on a list. The loading of the full list is quite long because it requires to go to a database via a WCF services and then to come back with the information.
In WPF 4.0 you have two different solutions:
- Retrieve the data on the UI Thread and wait after every add for the UI Thread to update. I don’t personnaly like this solution because this a kind of a hack and the interface reactivness remains odd.
- Tell the user to wait, then retrieve the data on a secondary Thread. Pass the information to the UI Thread and creates the list on it. This is usually what I do even if it’s degrade the code readability because it’s more complex to write.
Here is a an example of this second solution:
private void LoadUpPersonsClick(object sender, RoutedEventArgs e)
{
Task.Factory
//Retrieve the persons on another thread.
.StartNew>(RetrieveTheCollection)
.ContinueWith(t =>
{
foreach (var p in t.Result) _persons.Add(p);
},
//Continue on the UI Thread
TaskScheduler.FromCurrentSynchronizationContext());
}
public List RetrieveTheCollection()
{
List persons = new List();
for (int i = 0; i < 10; i++)
{
persons.Add(new Person() { Name = "Person " + i, Age = 40 + i % 5 });
}
return persons;
}
How do we do in WPF 4.5 ?
Life is really easier in WPF 4.5: all you have to do is to to enable the features via the EnableCollectionSynchronization method. For the record, I struggled a lot to find this method which is a static one of the BindingOperations class.
It takes two parameters: the collection on which access across multiple threads will be enabled and a object which will be used as a lock. Easy as this snippet:
//Creates the lock object somewhere private static object _lock = new object(); ... //Enable the cross acces to this collection elsewhere BindingOperations.EnableCollectionSynchronization(_persons, _lock);
There is one another overload which takes a CollectionSynchronizationCallback callback and a could-be-null context as additionna parameters. With this one you could decide which synchronisation mechanism to use instead of the default one which is the lock.
So as you can imagine, all the synchronisation work is done for you by the framework and the code you will finally end-up to write will be something like that:
private void AccessTheCollectionFromANonUIThreadClick(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(EditTheCollection);
}
public void EditTheCollection()
{
for (int i = 0; i < 10; i++)
{
_persons.Add(new Person() { Name = "Person " + i, Age = 20 + i % 5 });
}
}
It is clearly more readable, easy to understand and to write !
As usual, a full project can be found on my Dropbox folder after registration.
Thanks to the WPF team for this great new feature !
Regards,

