.NET / WPF Memory Leaks

Posted

This time I will try to cover few interesting issues that we can meet when we are creating WPF application.
Most of .NET developers are aware of the fact, that .NET is not perfect and could also cause memory leaks. I will show you few of them from the perspective of WPF application and how to prevent those.

1. Commands

When/WHy leaking

We use e.g. ICommand instance in ViewModel, to create binding in Views quite often. It’s almost default snippet for delegating View action to ViewModel in MVVM pattern. We create then “on demand” properties for them with getters, like below I used RelayCommand  implementation of interface ICommand to define a command.

It is very good solution and good way to create command only when the View part that is using it exists and binds to it.

What happens, when we remove this visual from UI (which is using such command)? Nothing special, visual element is removed, because binding contains weak reference to command. But the command still leaves in ViewModel. If we try to remove ViewModel from parent navigator, clean it up somehow, all it’s logic is removed, but those commands are not. Why? Because we didn’t inform GC to make it available for garbage collection, we need to set them to null – you probably knew that, but forgot about it 🙂

Another annoying side effect of this is that this command can keep other objects references in memory preventing them from being garbage collected. If you e.g. use some method this.MyExampleMethod()  inside the body of command handler you may cause in a situation when you removed ViewModel reference from memory, but it is still kept by this command and this can keep another references and so on. That is why it’s so important. Delegates memory leaks are really small – sever dozen of bytes, but it is still a memory leak.

How to prevent

I’ve used here MVVM Light framework, but it is just an example.

2. Event handlers

When/Why leaking

I think that you surely know about this, but just to cover all situations, I’ve added also this case. When we use event handlers we typically use delegates and set of handlers for it. Example?

As you can see, we add new handler that is a method in current class. And it is simple, when we won’t detach this method from delegate we will get memory leak. The reference to this event will be there, even . This is especially dangerous when we are recreating this event in a view model or control which is a part of collection. The items in collection are added and removed and we are not controlling when we should detach handlers. On the other hand, in such situations memory leaks are easy to observe e.g. in windows task manager.

How to prevent

It’s easy, always remember to detach handler from delegate.

info_outlineThere is one very important thing to mention when we are talking about handlers. You can observe sometimes that you have different behaviors and errors regarding memory between Debug mode and Release mode. Good example is below:

In such cases normally in Release mode we shouldn’t observe memory leaks, but in Debug we can. That’s because of code optimization. In Release mode (if opttimization is enabled) lambdas are wrapped in special way so that they are created as a part of parent class. If parent class is deallocated, same happens with lambda handlers. But in Debug that depends on optimization settings.

3. Non notifiable  source of binding

When/Why leaking

Some times we may forget to inherit our Binding source class from a class implementing INotifyPropertyChanged  or to implement it directly in our class. Let’s take a look on the code below:

If we use this item in e.g. ItemsControl template of item or anywhere in View e.g. like this:

We will get the CheckBox updated when we will update MyItem property. But what about bindings to IsSelected and Name properties of this object. First of all, Binsing mechanism need a source object to Bind from, so if it is not a DependencyProperty or object implementing  INotifyPropertyChanged  interface, WPF must create a special object for it of type System.ComponentModel.PropertyDescriptor and use its ValueChanged  event as a source of notifications, which must be created in runtime. The problem is that there is no event/trigger that will notify GC that this object should be removed from memory. Even when we remove control in UI, ViewModel in backend, the reference still exists. That causes memory leaks.

How to prevent

If we don’t use a valid implementation of  INotifyPropertyChanged in our source object class (here ListItem ), we can always clear this property by setting explicit null  to property MyItem  in notifiable ViewModel . That will cause our object to be garbage collected. Simple, but we sometimes forgot about those nuances.

info_outline
The only exception of this problem is when we are using Mode=OneTime  binding. Because in such cases the source object values are taken only once and there is no need to create any property descriptors in runtime for that.

4. Removing x:Name’d controls from C# code

When/Why leaking

That is a quite specific situation when we are removing some UI controls, that has been declared in XAML. Generally we can do it from own custom control implementation class or from code-behind in any UserControl.

WPF creates a reference to all named controls that can be then used from control code-behind. But we need to be aware that if we create a template or User control where we have visuals with strong names like below

We cannot just remove them in code-behind if we need it , like here:

How to prevent

We need to unregister them also, cause they are created globally, and there is no other way to remove them from memory. To do it we need to call method FrameworkElement.UnregisterName("nameOfControl") , to again notify GC about it. Something like this code below:

 

5. Non notifiable collections binding

When/Why leaking

A similar situation like in point 3. If we try to use a collection in our ViewModel, that is bound to View control property, and the collection is not implementing interface INotifyCollectionChanged, WPF mechanism will create a strong reference to this collection to make some kind of helper descriptor for it. The problem is that this reference will remain in memory for whole application lifetime.

How to prevent

I would suggest to use ObservableCollection<T> only for all observable collections used for binding items with View. As an alternative you can inherit own collection implementations by this class or implement required interface:  INotifyCollectionChanged.

Resources

JetBrains “Fighting Common WPF Memory Leaks with dotMemory”

Leave a Reply

Your email address will not be published. Required fields are marked *