Click here to Skip to main content
15,879,474 members
Articles / Desktop Programming / WPF

Improving the Performance of the WPF Dispatcher

Rate me:
Please Sign up or sign in to vote.
3.67/5 (3 votes)
19 Mar 2009CPOL2 min read 33.2K   282   12   2
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:

C#
//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)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralGood little step - My vote of 4 Pin
Bharath K A16-Mar-09 10:22
Bharath K A16-Mar-09 10:22 
GeneralAlternative implementation of OnCollectionChanged Pin
DimitrySTD16-Mar-09 0:26
DimitrySTD16-Mar-09 0:26 

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

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