{"id":1185,"date":"2011-08-10T00:00:00","date_gmt":"2011-08-10T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/the-top-5-wpf-and-silverlight-gotchas\/"},"modified":"2021-05-03T13:59:34","modified_gmt":"2021-05-03T13:59:34","slug":"the-top-5-wpf-and-silverlight-gotchas","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/the-top-5-wpf-and-silverlight-gotchas\/","title":{"rendered":"The Top 5 WPF and Silverlight Gotchas"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">As I&#8217;m sure you know, WPF and Silverlight both use XAML as their interface markup language. The idea is that you can define your user interface (UI) and bind it to data without ever writing a line of code (healthy skepticism advised). Whether or not you buy into that vision, the UI possibilities can be stunning, and it seems Microsoft has created a technology that combines both power and flexibility. However, with that power comes responsibility.<\/p>\n<p>It&#8217;s with an eye on that responsibility that I write this article, in which I want to talk about some of the problems that you can introduce into your application without even realizing it.<\/p>\n<h1>Background <\/h1>\n<p>.NET uses a garbage collector to reclaim and reuse the space left behind when objects are no longer needed. To do this, it builds a list of all objects that are still ultimately referenced from an application root, such as the stack, other objects on the heap, the CPU and statics, to name just a few. Everything else (i.e. objects which have no such references) is assumed to be garbage, and the .NET framework rearranges memory allocation to reuse the gaps these objects filled.<\/p>\n<p>A leak (or, if you&#8217;re being picky, leak-like behavior) occurs when a section of code fails to release references to objects it has finished working with. The smaller the leak, the greater the number of iterations that must occur before it becomes a noticeable problem. The larger the leak, the more obvious the problem.<\/p>\n<p>A really obvious example of this problem is adding an object to a static collection and then forgetting about it. Other common ones involve event handling, which we will discuss later. The simple fact is that if you leave a reference to an object behind, and that reference traces back to an application root, then you have a leak.<\/p>\n<p>There are lots of great articles about <a href=\"http:\/\/www.simple-talk.com\/dotnet\/performance\/the-top-5-.net-memory-management-misconceptions\/\">.NET memory management<\/a>, and one of the first things you can do to avoid leaks in general is to really understand memory management. <\/p>\n<h1>heavyweight User Interfaces in xaml<\/h1>\n<p>Silverlight and WPF applications are state-full, and allow us to hold state in the form of complex data structures as well as rich UI elements such as images and media. All of this &#8220;stuff&#8221; adds to the size of the views we create and, ultimately, the size of a memory leak when things go wrong. If you have a memory leak that involves a complex UI then it can quickly become a major problem, especially if users are constantly opening and closing windows as part of standard flows.<\/p>\n<p>Just as an example of how the way these problems can scale, this is exactly the situation I found with a large financial application written in WPF, employing all the usual accounting\/finance type windows, often containing many hundreds of rows of data. As you would expect, the developers had taken full advantage of data binding and the entity framework. It looked great and all seemed well until, during system testing, they discovered that the application would get slower over time and ultimately crash the machine. Eventually they actually had to reboot to get over it. Naturally I suspected a memory leak, but nothing could prepare me for the extent of the issues I actually found (but that&#8217;s a different story).<\/p>\n<p>Some of the issues we&#8217;ll cover are specific to WPF\/XAML and Silverlight, and others are general leaks you will get in any application. I thought it would be useful to go through the main technology-specific leaks you can easily create; thankfully, the good news is that they are easy to fix and avoid in the future.<\/p>\n<h1>WPF and Silverlight leaks<\/h1>\n<p>While I&#8217;ve tried to come up with a list of the most likely leaks, the trouble is that, depending on platform and framework versions, there are many potential leak mistakes you can make. Regardless, you&#8217;ve got to start somewhere, and these points will always serve you well. You&#8217;re likely to quickly see a pattern emerging in the underlying nature of the problems and solutions I highlight, but I do recommend you read to the end, because I almost guarantee that you&#8217;ll encounter one or more of these situations sooner or later.<\/p>\n<h1>Unregistered events (WPF + Silverlight, All versions)<\/h1>\n<p>Let&#8217;s start with the classic leak, common to all .NET applications &#8211; the event leak. While this is a common source of leaks for all .NET applications, it&#8217;s not a bug in .NET, but rather a common oversight by developers.<\/p>\n<p>Specifically, if you create an event handler to handle events occurring in some object, then if you don&#8217;t clear the link when you have finished, an unwanted strong reference will be left behind.<\/p>\n<h2>The Issue<\/h2>\n<p>My contrived example below deliberately isn&#8217;t specific to WPF\/Silverlight, but I include it because it&#8217;s a very common memory leak which all .NET applications are vulnerable to. In it I am subscribing to an <b>OnPlaced<\/b> event on my <b>Order<\/b> class. Imagine this code executes on a button click. Basically, it sets up an order for a currency exchange to take place when certain price conditions are met:<\/p>\n<pre>Order newOrder=new Order(\"EURUSD\", DealType.Buy, Price ,PriceTolerance, TakeProfit, StopLoss);\nnewOrder.OnPlaced+=OrderPlaced;\nm_PendingDeals.Add(newOrder);\n<\/pre>\n<p class=\"caption\">Listing 1<\/p>\n<p>When the price is right, an <b>Order<\/b> completes and calls the <b>OnPlaced<\/b> event, which is handled by the <b>OrderPlaced<\/b> method;<\/p>\n<pre>void OrderPlace(Order placedOrder)\n{\nm_PendingDeals.Remove(placedOrder);\n}\n<\/pre>\n<p class=\"caption\">Listing 2<\/p>\n<p>In the event handler, you can see that we are already eliminating a really common source of leaks; namely, references from collections (in this case the <b>m_PendingDeals<\/b> collection).<\/p>\n<p>However, the <b>OrderPlaced<\/b> event handler still holds a reference to the <b>Order<\/b> object from when we subscribed to the <b>OnPlaced<\/b> event. That reference will keep the <b>Order<\/b> object alive even though we have removed it from the collection. It&#8217;s <i>so<\/i> easy to make this mistake.<\/p>\n<h2>The Solution<\/h2>\n<p>The <b>OrderPlaced<\/b> method is just one line away from avoiding a memory leak!<\/p>\n<pre>void OrderPlaced(Order placedOrder)\n{\nm_PendingDeals.Remove(placedOrder);\nplacedOrder.OnPlaced-=this.OrderPlaced;\n}\n<\/pre>\n<p class=\"caption\">Listing 3<\/p>\n<p>The last line unsubscribes the event and removes the strong reference. If this is news to you, then drop everything and look at all your event handling code. Chances are you have a leak.<\/p>\n<h1>Databinding (WPF + Silverlight, All versions)<\/h1>\n<p>You read that right; data binding, the thing you rely on, can cause memory leaks. Strictly speaking it&#8217;s actually the way you use it that causes the leak and, once you know about it, it&#8217;s easy to either avoid or code around this issue.<\/p>\n<h2>The Issue<\/h2>\n<p>If you have a child object that data binds to a property of its parent, a memory leak can occur. An example of this is shown in Listing 4, below.<\/p>\n<pre>&lt;Grid id=\"strong\"&gt;mainGrid\"&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;TextBlock id=\"quot;txtMainText\"\" Text=\"{Binding ElementName=mainGrid, Path=Children.Count}\" \/&gt;\n&lt;\/Grid&gt;\n<\/pre>\n<p class=\"caption\">Listing 4: DataBinding Leak Example<\/p>\n<p>In this example, the condition will only occur if the bound property is a <b>PropertyDescriptor<\/b> property, as <b>Children.Count<\/b> is. This is because, in order to detect when a <b>PropertyDescriptor<\/b> property changes, the framework has to subscribe to the <b>ValueChanged <\/b>event, which in turn sets up a strong reference chain.<\/p>\n<p>If the binding is marked as <b>OneTime<\/b>, the bound property is a <b>DependencyProperty<\/b>, or the object implements <b>INotifyPropertyChanged<\/b>, then the issue won&#8217;t occur. In the case of <b>OneTime<\/b> binding this is because, as the name suggests, it doesn&#8217;t need to detect property changes, as the binding occurs from data source to consumer just once.<\/p>\n<h2>Solution<\/h2>\n<p>There are a number of work-arounds for this problem.<\/p>\n<ol>\n<li>Add a <b>DependencyProperty<\/b> [to the page\/window] which simply returns the value of the required <b>PropertyDescriptor<\/b> property. Binding to this property instead will solve the problem..  <\/li>\n<li>Make the binding <b>OneTime<\/b>\n<pre>Text=\"{Binding&#160;Path=Salary, Mode=OneTime}\"\/\n<\/pre>\n<p class=\"caption\">Listing 5<\/p>\n<\/li>\n<li>Add the following line of code on exit from the page:\n<pre class=\"lang:c# theme:vs2012\">BindingOperations.ClearBinding(txtMainText, TextBlock.TextProperty);<\/pre>\n<p class=\"caption\">Listing 6<\/p>\n<p>(This simply clears the binding and removes the reference.)<\/p>\n<\/li>\n<\/ol>\n<h1>Static events (WPF + Silverlight, All versions)<\/h1>\n<p>Subscribing to an event on a static object will set up a strong reference to any objects handling that event. Statics are a classic source of root references, and are responsible for a high proportion of leaks in code. <\/p>\n<p>Statics, once referenced, remain for the duration of the app domain execution, and therefore so do all their references. Strong references preventing garbage collection are just memory leaks by another name.<\/p>\n<p>To show you what I mean, the code below subscribes the calling class to the event source, <b>EventToLeak<\/b>, on the static object <b>MyStaticClass<\/b>:<\/p>\n<pre class=\"lang:c# theme:vs2012\">MyStaticClass.EventToLeak += new EventHandler(AnEvent);\n<\/pre>\n<p class=\"caption\">Listing 7<\/p>\n<p>The handling event, <b>AnEvent<\/b>, will be called when the <b>EventToLeak<\/b> event fires:<\/p>\n<pre class=\"lang:c# theme:vs2012\">protected override void AnEvent(EventArgs e)\n{\n\n\n&#160; \/\/ Do Soemething\n\n}\n<\/pre>\n<p class=\"caption\">Listing 8<\/p>\n<p>If you don&#8217;t subsequently unsubscribe the event, then it will leak because <b>MyStaticClass<\/b> continues to hold a strong reference to the calling class.<\/p>\n<h2>The Solution<\/h2>\n<p>To unsubscribe, simply add the code line:<\/p>\n<pre class=\"lang:c# theme:vs2012\">MyStaticClass.EventToLeak -= this.AnEvent;\n<\/pre>\n<p>This releases the strong reference from <b>MyStaticClass<\/b>. It&#8217;s a simple solution, but then it&#8217;s a simple problem &#8211; human error and oversight.<\/p>\n<h1>Command Binding<\/h1>\n<p>Command binding is a really useful feature in WPF; it allows you to separate common application commands and their invocation (such as Cut, Paste, etc ) from where they are handled. You can write your classes to handle specific commands, or not, and even indicate if those commands can be executed. As useful as these bindings are, you do have to be careful about how you use them.<\/p>\n<h2>The Issue<\/h2>\n<p>In the following example I am setting up some code within a child window to handle when <b>Cut<\/b> is executed within the parent <b>mainWindow. <\/b>I first create a <b>CommandBinding<\/b>, and then simply add it to the parent window&#8217;s <b>CommandBindings <\/b>collection.<\/p>\n<pre class=\"lang:c# theme:vs2012\">\nCommandBinding cutCmdBinding = new CommandBinding(ApplicationCommands.Cut, OnMyCutHandler, OnCanICut);  &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;mainWindow.main.CommandBindings.Add(cutCmdBinding);\n\n\n.....\nvoid OnMyCutHandler (object target, ExecutedRoutedEventArgs e)\n{\n&#160;&#160;&#160; \n&#160;&#160;&#160; MessageBox.Show(\"You attempted to CUT\");\n}\n\n\nvoid OnCanICut (object sender, CanExecuteRoutedEventArgs e)\n{\n&#160;&#160;&#160; e.CanExecute = true;\n}\n<\/pre>\n<p class=\"caption\">Listing 9<\/p>\n<p>You may be able to see what the problem is just from reading the code above because, at the moment, it leaks. It&#8217;s because we are leaving a strong reference in the main<b>Window.main.CommandBindings<\/b> object, pointing to the child. As a result, even when the child closes, it will still remain in memory due to the held reference.<\/p>\n<p>This is obviously a contrived example to illustrate the point, but you can easily set this scenario up without even realizing it.<\/p>\n<h2>The Solution<\/h2>\n<p>Again, the solution couldn&#8217;t be easier and, not surprisingly, involves removing the command binding reference:<\/p>\n<pre class=\"lang:c# theme:vs2012\">mainWindow.main.CommandBindings.Remove(cutCmdBinding);\n<\/pre>\n<p class=\"caption\">Listing 10<\/p>\n<p>Once this reference is removed, the leak will go away.<\/p>\n<h1>DispatcherTimer Leak<\/h1>\n<p>Improper use of the <b>DispatcherTimer<\/b> will cause a memory leak. There&#8217;s not much more background to this, so let&#8217;s just jump right in.<\/p>\n<h2>The problem<\/h2>\n<p>The code below creates a new <b>DispatcherTimer<\/b> within a user control. A textbox is updated with the contents of the count variable, which is updated every second by the <b>DispatcherTimer<\/b>. To make it easier to see the leak, I have also added a byte array called <b>myMemory<\/b>, which just makes the leak much bigger and easier to see.<\/p>\n<pre class=\"lang:c# theme:vs2012\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; public byte[] myMemory = new byte[50 * 1024 * 1024];\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; int count = 0;\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; private void MyLabel_Loaded(object sender, RoutedEventArgs e)\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; {\n\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _timer.Interval = TimeSpan.FromMilliseconds(1000);\n\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _timer.Tick += new EventHandler(delegate(object s, EventArgs ev)\n\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; count++;\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; textBox1.Text = count.ToString();\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; });\n\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _timer.Start();\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; }\n<\/pre>\n<p class=\"caption\">Listing 11<\/p>\n<p>On my main window, I am adding an instance of the <b>UserControl<\/b> to a <b>StackPanel<\/b> (after removing children first) on a button click. This will leak memory for every button click and, as mentioned a moment ago, in this example the main leak you will see is the byte array. Tracing it backwards (using <a href=\"http:\/\/www.red-gate.com\/products\/dotnet-development\/ants-memory-profiler\/index?utm_source=simpletalk&amp;utm_medium=article&amp;utm_content=wpfwilverlightgotchas&amp;utm_campaign=antsmemoryprofiler\">ANTS Memory Profiler<\/a> in this case, though any profiling tool will do) shows that the <b>UserControl<\/b> as the source of the leak.<\/p>\n<p>This probably feels familiar, as the problem is once again a reference being held, this time by the <b>Dispatcher<\/b>, which holds a collection of live <b>DispatcherTimers<\/b>. The strong reference from the collection keeps each <b>UserControl<\/b> alive, and therefore leaks memory.<\/p>\n<h2>The Solution<\/h2>\n<p>The solution is really simple but easy to forget and, you guessed it, you&#8217;ve got to stop the timer and set it to null. Here&#8217;s the code to do that:<\/p>\n<pre>_timer.Stop();\n_timer=null;\n<\/pre>\n<p class=\"caption\">Listing 12<\/p>\n<h1>TextBox Undo Leak<\/h1>\n<p>The last leak I want to draw your attention to is not really a leak; it is intended behavior, but it&#8217;s important to know it&#8217;s there. <\/p>\n<h2>The Problem<\/h2>\n<p>The problem is to do with the <b>TextBox<\/b> control and <b>UNDO<\/b>. TextBoxes have built-in undo functionality, enabling a user to undo their changes to the contents of a text box. To achieve that, WPF maintains a stack of recent changes, and when you use a memory profiler, you can clearly see a build up of data on this undo stack.<\/p>\n<p>This isn&#8217;t a major problem unless your app is updating large strings to text boxes over many iterations. The main reason to note this behavior is because it can often show up on memory profile traces, and there is often no point being distracted by it.<\/p>\n<h2>The solution<\/h2>\n<p>You can limit the behavior of the undo stack by either switching it off:<\/p>\n<pre>textBox1.IsUndoEnabled=false;\n<\/pre>\n<p class=\"caption\">Listing 13<\/p>\n<p>Or alternatively you can reduce its impact by setting the <b>UndoLimit<\/b> property:<\/p>\n<pre>textBox1.UndoLimit=100;\n<\/pre>\n<p class=\"caption\">Listing 14<\/p>\n<p>This limits the number of actions that can be undone, in this case to 100. By default the setting is -1, which limits the number of actions only by the amount of memory available. Setting the value to zero also switches undo off.<\/p>\n<h1>Conclusion<\/h1>\n<p>None of this is rocket science, and it&#8217;s all based on the same principle: &#8220;<i>leave a reference behind and potentially you have a leak<\/i>&#8220;. Obviously that depends on whether the left reference is ultimately connected to a root reference.<\/p>\n<p>While nothing I have covered is strictly speaking a bug, all of the points are definitely gotchas that you can easily be caught by without realizing it. I should know, because I see them all again and again in the projects that I work on. <\/p>\n<p>Ultimately, the two things I recommend you do to avoid memory leaks in the future are:<\/p>\n<ul>\n<li>Learn all you can about .NET memory management and how your code impacts it  <\/li>\n<li>Get used to routinely using a memory profiler and interpreting it&#8217;s results to trace issues such as the many potential flavors of left behind strong references. <\/li>\n<\/ul>\n<div class=\"newsletter-subscribe newsletter-subscribe-default\">\n<h3>Get notified&#8230;<\/h3>\n<p>Ricky is working hard to prepare more essential Top Tips for you. Drop your email address in the field below, and you&#8217;ll be one of the first to know when more .NET know-how and handy free resources are ready&#8230;<\/p>\n<p class=\"newsletter-subscribe-loading-message\">Subscribing&#8230; <\/p>\n<p class=\"newsletter-subscribe-success-message\">Successfully subscribed <\/p>\n<p class=\"newsletter-subscribe-error-message\">Error <\/p>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>As WPF and Silverlight sit on the .NET framework, they&#039;re subject to the rules of the Garbage Collector. That means there are a few unique ways in which WPF will cause your application to leak memory, and Chris Farrell points out the most prominent culprits.&hellip;<\/p>\n","protected":false},"author":221880,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,5093,4206,4838,5432],"coauthors":[],"class_list":["post-1185","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-ants","tag-performance","tag-silverlight","tag-wpf"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1185","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221880"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1185"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1185\/revisions"}],"predecessor-version":[{"id":42696,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1185\/revisions\/42696"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1185"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}