Telerik blogs

In a previous post I talked about some great new features in the newest (2013 Q2) release of JustTrace. The new features are terrific and certainly contribute to make JustTrace an indispensable part of any .NET developer’s toolbox, but there are three features that are so cool that they are deserving of their own individual blog posts:

I covered the Disposed Object View in the previous post in this series. I’ll be demonstrating the Bottlenecks View in the next post in this series. Today I’m going to show you how the Potential Binding Leaks in WPF View can help you writer better WPF applications.

Getting to Know WPF

WPF (Windows Presentation Framework) is Microsoft’s preferred stack for building desktop Windows applications in .NET. One of the most obvious benefits of using WPF over conventional WinForms is that it’s XAML & code-behind architecture enables developers and designers to work together to create applications that are well designed and very user friendly. Its use of vector based rendering makes the forms easier to work with in terms of layout and resizing and enables designers to create controls of visual aspects that just were not practical (or even possible) in the bitmapped WinForms world. But from an architectural point of view, this is not the most compelling reason to use WPF over its predecessor.

In most WinForms applications the logic that controlled the user interface and interacted with the rest of the applications was tightly bound the visual aspects of the user interface. In many cases this code was actually in the event handlers for the various controls on the form. This tight coupling of logic and presentation made the individual parts of the form inflexible and made unit testing difficult.

In WPF the XAML that is used to define the front end is decoupled for the code (C# or VB.NET) that defines the logical functionality and controls the interactions between the form and the rest of the application. This makes both sides more flexible and makes unit testing the logic for the form much easier. This new paradigm gave rise to a new architectural pattern; Model-View-ViewModel. The MVVM pattern simplifies the interaction between the XAML based front end and the code based code behind by providing data binding facilities for your form. An introduction to the MVVM pattern, including some examples can be found here.

While WPF and the MVVM patterns have been a great help to Windows developers, they are not immune to resource issues. Memory leaks can occur in WPF if you data-bind to a view that does not implement INotifyPropertyChanged, don’t have their binding mode set to OneTime and are not using Dependency Properties. What happens in this case is that the runtime will attempt to use the ValueChanged event, which in turn calls The AddValueChanged event on PropertyDescriptor. This in turn creates a strong reference to the binding target. Not necessarily a common situation, but troubling none the less. A more detailed discussion of this phenomenon can be found here.

Never Fear, JustTrace is Here!

On a large project, finding these WPF leaks can be difficult. In most cases developers don’t really know what they are looking for due to the fact that WPF uses reflection to access bound properties, which prevents these problems from being discovered by static code analysis tools. The good news is that one of the newest features of JustTrace is to find and report these leaks.

To demonstrate this, I asked my fellow Evangelist and WPF Ninja Carey Payette to throw together a quick application that has one of these leaks. The application Carey created is a small WPF application that displays a window (as shown in Figure 1) with two types of cars that I can select by clicking on either one:

clip_image001

Figure 1 – The leaky WPF form

The ViewModel for this application returns a list of cars that are then bound the elements of the form. The key is that this ViewModel does not implement INotifyPropertyChanged:

 

 1: public class ViewModel
 2:     {
 3:  private List<Car> _carList;
 4:  
 5:  public List<Car> CarList
 6:         {
 7:             get {
 8:                 Car car1 = new Car() { CarMake = "Volkswagen", CarModel = "Bug", CarImagePath=@"Images/Car1.jpg" };
 9:                 Car car2 = new Car() { CarMake = "Audi", CarModel = "Prototype", CarImagePath=@"Images/Car2.jpg" };
 10:                 _carList = new List<Car>();
 11:                 _carList.Add(car1);
 12:                 _carList.Add(car2);
 13:  return _carList; 
 14:             }
 15:             set { _carList = value; }
 16:         }
 17:     }

 

To use JustTrace to find this memory leak I’ll select “Memory Profiler” from the JustTrace toolbar in Visual Studio (as shown in Figure 2)

clip_image003

Figure 2 – Memory profiling has been selected

I run the application by either hitting Ctrl+F5 or selecting “Start Without Debugging” from the “Debug” menu. My application will start and JustTrace will start profiling the application. When the application window appears I will switch back and forth between the selected cars a few times, then go back to Visual Studio and in the JustTrace widow click the “Kill & Get” button (shown in Figure 3) to take a memory snapshot then close the application:

clip_image004

Figure 3 – The Kill & Get button takes a memory snapshot then ends the application

Once the application is closed JustTrace will display the snapshot summery for the last snapshot taken (showing in Figure 4)

clip_image006

Figure 4 – The JustTrace snapshot summery

To see if my WPF application has any leaks related to data binding I can click on the “Potential Binding Leaks in WPF” option under the “Analyses” group. This will show me a list of classes that could be leaking memory in my WPF application (shown in Figure 5):

clip_image008Figure 5 – Potential data binding leaks in WPF

Sure enough it looks like our ViewModel has been identified as a potential leak. It’s interesting to note that the Car class has also been identified as a potential leak, which makes sense as it essentially acts as a view model in this case. I can eliminate these leaks by having each class (ViewModel and Car) implement INotifyPropertyChanged. You can see the results of these changes by profiling the application again and observing that there are no potential binding leaks found. (Figure 6)

clip_image010

Figure 6 – No potential binding leaks found

This is a relatively small application. There is only one form and the data being bound is very simple, thus the total leak is 52 bytes and probably not a significant source of resource issues. However, in even a more simple production application (especially one where the data to be bound is coming from a larger data store) those numbers could become huge and quickly represent a major memory issue.

Summary

WPF provides a great way to quickly and easily develop sophisticated front ends for desktop Windows applications. But it can also enable developers to create memory leaks that can be difficult to detect and isolate. In business applications with many forms and large amounts of data these leaks can create critical memory resource issues. JustTrace will find these WPF specific leaks and quickly bring them to your attention. This feature is only available in the 2013 Q2 release of JustTrace. So if you don’t already have JustTrace download the trial today and make sure your WPF applications are leak-free! JustTrace banner

About the Author

James Bender

is a Developer and has been involved in software development and architecture for almost 20 years. He has built everything from small, single-user applications to Enterprise-scale, multi-user systems. His specialties are .NET development and architecture, TDD, Web Development, cloud computing, and agile development methodologies. James is a Microsoft MVP and the author of two books; "Professional Test Driven Development with C#" which was released in May of 2011 and "Windows 8 Apps with HTML5 and JavaScript" which will be available soon. James has a blog at JamesCBender.com and his Twitter ID is @JamesBender. Google Profile

Comments

Comments are disabled in preview mode.