Click here to Skip to main content
Click here to Skip to main content

Improving the Performance of the WPF Dispatcher

, 19 Mar 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
How to improve the performance when using a Dispatcher for WPF

Introduction

My little list is an improvement of the ObservableCollection<T> to handle multithreading. And (that is the clue) just do the event handlers from the foreground thread in the foreground thread. This results in a great boost of performance for me.

Background

My first approach was to give my collection a Dispatcher to invoke the CollectionChanged events. This resulted in some performance problems because I do some searching in my own handlers. With the new list, only the WPF handlers are done in the foreground thread, which is of course much faster.

Using the Code

You can use my collection as a normal Observed Collection. I still have some synchronization issues because Microsoft does not use a thread safe enumeration. If anyone has a clue as to how we can improve this, please tell me.

Here is the tricky part of the collection:

//Override the event to be able to get the invocation list
public override event NotifyCollectionChangedEventHandler CollectionChanged;

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    if (CollectionChanged != null)
    {
        //get all Delegates
        foreach (Delegate del in CollectionChanged.GetInvocationList())
        {
            // look for a Dispatcher
            PropertyInfo prop = del.Target.GetType().GetProperty("Dispatcher");
            if (prop != null)
            {
                //Foreground Thread Invoke
                (prop.GetValue(del.Target, null) 
                      as Dispatcher).BeginInvoke(del, this, e);
            }
            else
            {   
                //Linear Invoke not in Foreground thread
                del.DynamicInvoke(this, e);
            }
        }
    }
}

Advanced Thread Safety

Because Microsoft does not care about checking the CollectionChangedEvents, I needed to do it on my own. This will happen before I tracked the operations posted to the WPF Dispatcher:

  1. Lock the list (this prevents the Dispatcher from processing the events you post)
  2. Add an item
  3. Remove the item again
  4. Release the lock on the list (the Dispatcher is now able to Update)
  5. The Dispatcher tries to access the element at index 1 from step 2, and crashes because at this time the item is not in the list

I modified the OnCollectionChanged of the Collection to track down the Operations that I get from DispatcherInstance.BeginInvoke. So on each event, I first check the previous Operations and if they interfere with the actual action. When an Operation is completed, I remove it from the tracking. This is not completely functional at the moment, so if you try my collection please give me some feedback as to how the handling can be improved. So this is how it's going now:

  1. Lock the list
  2. Add an item
  3. Remove the item again
  4. Detect that the operations from step 2 and 3 remove each other and cancel both
  5. Release the lock
  6. The Dispatcher is fine

History

  • 15 Mar 2009: Initial version
  • 19 Mar 2009: Added thread safety extensions

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Erodan

Germany Germany
No Biography provided

Comments and Discussions

 
GeneralGood little step - My vote of 4 PinmemberBharath K A16-Mar-09 11:22 
GeneralAlternative implementation of OnCollectionChanged PinmemberDimitrySTD16-Mar-09 1:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411019.1 | Last Updated 19 Mar 2009
Article Copyright 2009 by Erodan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid