DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

WPF 4.5 – Part 7 : Accessing Collections on non-UI Threads

Jon Antoine user avatar by
Jon Antoine
·
Aug. 15, 12 · Interview
Like (0)
Save
Tweet
Share
9.34K Views

Join the DZone community and get the full member experience.

Join For Free

weakEventHere is the seventh (OMG !) post on the WPF 4.5 new features. Collections are a part of every application and their management is probably 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 times, 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 Thread 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 this in WPF 4.0?

Let’s say that you have an application which display people on a list. The loading of the full list is quite long because it requires the program 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:

  1. 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 is kind of a hack and the interface reactivness remains odd.
  2. Tell the user to wait, then retrieve the data on a secondary Thread. Pass the information to the UI Thread and it creates the list on it. This is usually what I do even if it degrades 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 this 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 method 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 additionnal parameters. With this one you could decide which synchronization 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 writing 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 easier 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 !

 

Windows Presentation Foundation

Published at DZone with permission of Jon Antoine, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Mr. Over, the Engineer [Comic]
  • The Quest for REST
  • Upgrade Guide To Spring Data Elasticsearch 5.0
  • How to Create a Real-Time Scalable Streaming App Using Apache NiFi, Apache Pulsar, and Apache Flink SQL

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: