Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Improving the Performance of the WPF Dispatcher

0.00/5 (No votes)
19 Mar 2009 1  
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here