Can bindings create memory leaks in WPF?

28,926

Solution 1

If you are not binding to a DependencyProperty or a object that implements INotifyPropertyChanged then the binding can leak memory, and you will have to unbind when you are done.

This is because if the object is not a DependencyProperty or does not implement INotifyPropertyChanged then it uses the ValueChanged event via the PropertyDescriptors AddValueChanged method. This causes the CLR to create a strong reference from the PropertyDescriptor to the object and in most cases the CLR will keep a reference to the PropertyDescriptor in a global table.

Because the binding must continue to listen for changes. This behavior keeps the reference alive between the PropertyDescriptor and the object as the target remains in use. This can cause a memory leak in the object and any object to which the object refers, This includes the data-binding target.

So in short if you are binding to a DependencyProperty or INotifyPropertyChanged object then you should be ok, otherwise like any subscribed event you should unsubscribe your bindings


Edit: There is a possibility this was fixed in .NET4.5 using Weak Events/References, But after a few quick tests it seemed the same to me, I will have to dive in more deeply to confirm, so I'll personally say in might be fixed in 4.5 :)

Solution 2

Not pretend to answer, just for reference. In a classic article on Finding Memory Leaks in WPF-based applications author Jossef Goldberg, described in detail cases, where there may be a memory leak in WPF application. Really, most relate to the .NET 3.5/4.0, but some cases may be relevant to this day. Also, have a small extension.

Quote about leak in Binding:

Cause:

This leak documented in this kb article. It is triggered because:

The TextBlock control has a binding to an object (myGrid) that has a reference back to the TextBlock (it is one of myGrid children’s).

Note: that this type of a DataBinding leak is unique to a specific scenario (and not to all DataBinding scenarios) as documented in the kb article. The property in the Path is a not a DependencyProperty and not on a class which implements INotifyPropertyChanged and in addition a chain of strong references must exist.

Code:

myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid; 
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);

Same leaky code can be also written in XAML:

<TextBlock Name="MyTextBlock" 
           Text="{Binding ElementName=myGrid, Path=Children.Count}" />

Fix/Workaround:

There are few of approaches, the easiest one is simply to clear the binding when the windows is about to close.

e.g.:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);

Other approach is to set the mode of the data binding to OneTime. See the kb article for other ideas.

Useful link:

Avoiding a WPF memory leak with DataBinding

Solution 3

From http://msdn.microsoft.com/en-us/library/aa970850.aspx, WPF uses Weak Event Patterns, which do not hold strong references to objects and allow them to be GC'ed if they are the only references to an object.

"Many aspects of WPF data binding already have the weak event pattern applied in how the events are implemented."

But weak events are only used on DependencyProperties and INotifyPropertyChanged object, so if you are binding to a POCO with a binding mode other than OneTime you could end up leaking memory.

Share:
28,926
James Joshua Street
Author by

James Joshua Street

Updated on January 20, 2022

Comments

  • James Joshua Street
    James Joshua Street over 2 years

    Do I need to unbind items as the item disappears in order to prevent memory leaks? I guess I'm just a little worried that if I reload and a new template is applied to a control, and in that template there exists a binding to an outside element, could that prevent the control made for the template from being garbage collected?

  • Mario Vernari
    Mario Vernari over 10 years
    @sa_ddam213: both the DP and INotifyPropertyChanged are safe for sure. Anyway, are you sure about the PD? I mean that the things should have turned fine on the latest .Net 4.5 framework, where the WeakEvent-pattern is used intensively.
  • sa_ddam213
    sa_ddam213 over 10 years
    I just double checked with .NET4.5 and it still seems to leak when PropertyDescriptor is used, If you want to confirm I used Jossef Goldberg's leak tested for WPF and recompiled to 4.5, link:blogs.msdn.com/b/jgoldb/archive/2008/02/04/…, I have not tested to much into the leaks in 4.5 as the leaks in bindings in the previous framework versions changed my WPF coding habits permanently to avoid the issue :), I hope it is fixed and I will add disclaimer above about 4.5
  • 3615
    3615 over 7 years
    What about bindings to ReadOnly properties? For example, binding to ExpressionBody member? public string Test => "TestString";
  • Julien Christin
    Julien Christin over 5 years
    Note: the memory leak issue mentioned above only occurs when the binding mode is OneWay or TwoWay. If the binding is OneTime or OneWayToSource the CLR won't create a strong reference event if the bound property is not a DependencyProperty or if the bound object does not implement INotifyPropertyChanged.
  • FKDev
    FKDev almost 5 years
    Would it possible to browse all the bindings in the visual tree of a user control, detect if there are the wrong kind and clear them ? Or why not clear all the binding whatever their kinds using BindingOperations.ClearBinding in the unload event. Or is stupid for some reason ?
  • Lumo
    Lumo almost 4 years
    It is not fixed. .NET Framework 4.7.1 has the same behavior.
  • Alexander Høst
    Alexander Høst over 2 years