WPF Binding Bug leads to possible Memory Issues
Update: this bug is no where near as bad as I first suspected. I am instead going to supercede this post with a post about event handlers.
Update: I have reported this bug to MSDN Connect here. If you are a WPF developer please vote, as I can virtually guarantee this will affect your applications at some point too
As a Windows Forms or Windows Presentation Foundation developer, it is important to be aware of how event handlers and the .NET garbage collector work. A very common scenario that lands developers in trouble is this:
In this scenario, some code in a Window is subscribing to an event on a static object instance. To be a little more generic, the Window represents an object with a “short lifecycle” (we new()‘ed it up, and we’ll stop using it), and the static object represents an object with a “long lifecycle” (longer than the Window).
The reason this can be problematic comes from the way event handlers work. When the Window subscribes to an event handler on the Static Object, the Static Object actually has a reference back to the Window:
If you are familiar with .NET garbage collection you’ll recognize the problem: since the “long-lived” or static object is still in scope (since it is “static”), the reference it keeps to the Window means that the Window will never be reclaimed by the garbage collector whilst the Window is still subscribed to the event.
This creates a problem - if you forget to unsubscribe your event handlers (-= in C#, or RemoveHandler in VB.NET), the memory used by expensive objects like Windows (and all of the controls and data they contain) may never be reclaimed while your application is running. We’ve seen cases where hundreds of MB have been wasted due to static event handlers alone.
Weak Event Handlers
If you’ve used .NET for some time you may have heard of the WeakReference class. The idea of a weak reference is that you can still reference the other object, but the garbage collector will ignore the reference when it is figuring out what memory to collect.
Weak references can be used in clever ways so that event handlers can be weak referenced too. The basic idea is to introduce a proxy object into the middle:
This trick breaks the chain so that your short-lived object (the Window) is not referenced by the long-lived object (our Static Object). The static object will still have a direct reference to the proxy object (our Weak Event Handler class), but this is a lightweight class so it’s not so bad. As part of the destructor of our Window, we can unsubscribe the event handler too, so that no memory is kept laying around.
Some good examples of how to implement weak references can be found here:
Alternatively, if you are using WPF, you can make use of the new WeakEventManager class.
WPF Binding Bug
This brings me to the reason for my post. If you’re using WPF, you’re probably (at least, I hope) making use of the INotifyCollectionChanged interface, either directly or through the use of classes like the ObservableCollection<T>. This interface provides an event, named CollectionChanged, which allows the collection to tell the bound UI element that the items in the collection have changed.
Can you guess where this is going?
When you bind to an object implementing INotifyCollectionChanged, WPF automatically subscribes to the CollectionChanged event on the object. This means your collection has a reference back to your UI element - which has references to your Window, and so on.
So, if you happen to bind to a static or long-lived instance of a collection (a cache, for example), you’re in a lot of trouble.
I have uploaded a sample project - tested against .NET 3.0 and 3.5 - which reproduces the problem. I haven’t yet found a workaround (setting the DataContext/ItemSource properties to null when closing don’t seem to help), so my only suggestion so far would be to be very wary of binding to static objects or objects which will live longer than your Window
Download sample project (VS2008 format).
Technorati tags: wpf, memory management, binding
Filed under: WPF

They call this the lapsed-listener scenario and I blogged about it a while ago from the context of WebForms http://damieng.com/blog/2005/01/19/lapsedlistenersmemoryleaksinsubscriberpublisherscenarios
It didn’t help that WeakReferences were (still are?) a little buggy and many of the solutions proposed on the blogs have problems of their own you won’t find immediately.
Ideally the objects should be released whenever possible to avoid the problem in the first place. Where that isn’t possible because the framework doesn’t call you back (e.g. WebForms) then a proxy should be used that itself uses a WeakReference.
If you are interested in a WeakReference for .NET then also look at http://damieng.com/blog/2006/08/01/implementingweakreferencet
[)amien
Thanks for this.
Just today I managed to track down a bug that has been causing me grief for the last few days to this exact issue.
The BUG with the Data Binding model is very interesting.
IMHO To solve this problem, you should manually unsubscribe the “binded†object from the ObservableCollection.CollectionChanged event.
Also you didn’t mention that INotifyPropertyChanged interface has the PropertyChanged event. You should also unsubscribe from this one for each single object.
Good work, thanks.
Hi Tomer,
I’m not sure if you can force the UI control to unsubscribe. There seems to be some cases where it will unsubscribe if you set the DataContext to null, and other cases where it doesn’t (the ItemsSource on a ListBox, for example).
And yes, PropertyChanged is another event we should watch out for. CollectionChanged is a little more dangerous since a collection is likely to be more expensive than a single object, but they are both still very problematic.
Cheers,
Paul
Hi Damian,
Good blog post. Sorry it took so long for your comment to appear - WordPress stopped notifying me of new comments to authorize and the links you included in your comment tripped the spam filter thingo.
Paul