I've found that the chart controls in the WPFToolkit library leak memory. I am using them in an MVVM setup, where I bind the ItemSource of the chart control (PieSeries or BarSeries) to an ObservableCollection on my ViewModel. I sometimes Clear() the ObservableCollection and then Add() new KeyValuePairs to it (when the user triggers a SelectionChanged event on a ComboBox to see a different set of data). That's how I change the data in the chart. However, the memory is not released. I've found that if I comment out the control in the XAML, the memory problem goes away, even if I still Add to the collection.
Are there any good fixes for this memory leak? Or alternative toolkits that are free?
Thanks!
This seems to be a known issue, here is a quick fix:
<dvc:Chart.Palette>
<dv:ResourceDictionaryCollection>
<!-- Note: This a memory leak fix, do not remove-->
</dv:ResourceDictionaryCollection>
</dvc:Chart.Palette>
Found here: http://wpf.codeplex.com/discussions/216609
Related
While researching potential causes of memory leaks in WPF applications I came across this article:
https://oz-code.com/blog/net-c-tips/top-3-memory-leak-inducing-pitfalls-of-wpf-programming
This article makes the following unsubstantiated claim (which it admits to) that binding to collections other than ObservableCollection cause leaks:
Avoid binding to collections that are not ObservableCollection
I’m a bit sketchy on the details on this one. I haven’t yet been able
to find the root cause of this issue, or find any corroborating blog
post or MSDN articles, but still: in several instances, I’ve found
memory leaks occurred when an ItemsControl was bound to an ICollection
that isn’t an ObservableCollection, and changing it to an
ObservableCollection solved the problem.
Is this an accurate statement? Or is there some other more likely explanation?
I wonder if what the OP described might have been caused by binding to objects that don't implement INotifyPropertyChanged? (https://stackoverflow.com/a/18543350/3195477).
Not exactly quite what the OP asked, but close enough to help, I hope: https://blog.jetbrains.com/dotnet/2014/09/04/fighting-common-wpf-memory-leaks-with-dotmemory/ states:
Collection binding leak
A similar issue to the WPF binding leak is the
Collection binding leak. If there is binding to a collection that does
not implement the INotifyCollectionChanged interface, WPF creates a
strong reference to this collection. As a result, it stays in memory
for the entire application lifetime.
Working with WinForms you have to free memory after using gdi objects, event handlers, objects from native code, etc.
In WinForms I used to remove for example event handlers in the dispose method.
What is the best workaround to prevent memory leaks in Wpf? Is it the same as in Winforms using Dispose pattern? At all, do I have to care about event handlers, gdi objects in Wpf? What about the runtime created resources(Brushes, etc)?
This blog post lists the most common situations that cause memory leaks in WPF applications.
Event handlers to objects in parent windows
Registering to events from static objects
Using timers
Data binding
Changing the Text property of a text box
It also describes how to fix these common issues.
Another good approach is to develop an app while following the standard guidelines and then use some kind of profiler to determine any memory leaks or performance bottlenecks.
From MSDN: Any WPF framework-level element (those objects deriving from either FrameworkElement or FrameworkContentElement) has three common lifetime events: Initialized, Loaded, and Unloaded.
.....
Unloaded is raised last and is initiated by either the presentation source or the visual parent being removed. When Unloaded is raised and handled, the element that is the event source parent (as determined by Parent property) or any given element upwards in the logical or visual trees may have already been unset, meaning that data binding, resource references, and styles may not be set to their normal or last known run-time value.
Some helpful links on WPF resource dictionary leaks:
DynamicResource\StaticResource cause memory leaks
Memory leak problem with ResourceDictionary and MergedDictionaries
Watch out for events: it's very easy to miss something, because all references from the delegate will exist until the delegate lives. I suggest to use weak event pattern when it's possible. Actually Microsoft uses it in their Prism framework.
http://msdn.microsoft.com/en-us/library/aa970850.aspx
Also check out an issue that I was catched by many times when learning WPF http://support.microsoft.com/kb/938416/en-us
Recently I noticed serious memory leak in my WPF project. If simplify the project, it has a login form and a main form. In main form there are 1 user control which is composed of about 30 user controls and 3 buttons, 1 user control which has 3 buttons and a Infragistics datagrid. I use background worker to query DB every 30 sec only for the datagrid.
After I logout of the main form using main form.closed and re-launch the login window, I noticed that every time there is 6-7MB increase measured by ANTS memory profiler 7. Even though I have unregistered event handlers, set variables to null and called GC.Collect(), memeory leak is still the same. My questions are:
1. Why close wpf window doesn't release the memory and resource? I can see many strings(most of them are from GUI) are still in memory after close window by ANTs profiler.
2. Do I need to unregister the events defined by resource event setter? Do I need to unregister the events declared in XAML?
3. From WPF memory leak, people said we should not use GC.Collect(), but I do see a little improvement. Shall we use it or not?
I have had a simillar problem while using WindowsFormsHost for PictureBox control.
The WPF window using WF PictureBox control could not be fully released and that's why i had a regular ~10mb increase everytime i re-opened the subwindow.
The problem was solved since i started nulling the WFH object on WPF window closing.
Just make sure You clear all the WF controls if You use such.
Break into the debugger and then type this into the Immediate window:
.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll
The path to sos.dll varies. The way to find out the correct path is to look for mscorwks.dll in the Modules pane. Wherever that is loaded from is the correct path for sos.dll.
Then type this:
System.GC.Collect()
That will ensure anything not reachable is collected. Then type this:
!DumpHeap -type <some-type-name>
This will show you a table of all existing instances, with addresses. You can find out what is keeping an instance alive like this:
!gcroot <some-address>
originally answered by Daniel
It depends. User controls in WPF do not inherently dispose, so you will have to override the functionality and allow it in your controls with:
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx
But to your point, you will need to do a GC.Collect() at least once as SlimGG suggests.
In most cases, calling the garbage collector directly is considered bad practice because it is not calling it for your control specifically, but for all objects queued for disposal.
When a user clicks on a WinForms menu item, this code gets executed:
// this is an Infragistics XamRibbonWindow
var someWpfInfragisticsWindow = new SomeWpfInfragisticsWindow();
ElementHost.EnableModelessKeyboardInterop(someWpfInfragisticsWindow);
someWpfInfragisticsWindow.Show();
The window that is shown is an Infragistics XamRibbonWindow. It also contains an Infragistics XamDataGrid whose DataSource is bound to an IEnumerable property on the view model.
The window also contains a 'Search' button that will retrieve a new collection of items from a database, and set the previously mentioned view model property. This causes the grid to display the new collection.
Later on, the user may close the window. No code was written to handle the close.
My questions are:
Does closing the window dispose of the window, its controls and make the collection bound to it GC-able (assuming no other references to the collection exist)?
Does anyone see any potential memory issues with what I've described? Perhaps with the way the items displayed by the grid is updated (or anything else)?
When the Window is closed if you haven't held a reference to it it should be available for garbage collection. I don't see any memory issues with this approach from the details provided.
Note that Infragistics does have some static classes that will remain after you close the window.
If you do have memory leak issues using the Infragistics controls and believe that the controls may be the cause you should reach out to Infragistics for assistance determining the cause of the leak. There are links to post on the forums or submit a support case from the get help page.
Some months ago I started developing a Silverlight application on my own. I quickly discovered that I was unable to get expected garbage collection for most of my controls. I struggled for about a week with WinDBG and ANTS memory profiler and then found the "DataTemplate memory leak" strand on the Silverlight forum (http://forums.silverlight.net/forums/t/171739.aspx).
Given that so many people seemed to be frustrated with various memory issues I decided to delay further investigation into the memory situation until the most obvious issue was resolved.
Anyway, now I'm looking into the issue again and I realise that the problem I'm having is much more fundamental than I had first thought. I simply don't have a paradigm for writing garbage collectable Silverlight controls when: a) the control has dependency properties that can be bound to, and b) the control can be unloaded from one control and then subsequently loaded again.
I'm starting to think that the second of these demands is too great. Can anyone confirm this?
To give a tiny bit more detail, the most robust pattern I can come up with for writing good, garbage collectable Silverlight controls is as follows:
1) When a Control's Template is applied (in the OnApplyTemplate override) I setup any internal bindings between local properties and TemplateParts. For example, I might setup a Binding between a local property called CanSearch and a button.
if (x_Button_Search != null)
{
Binding b = new Binding("CanSearch");
b.Source = this;
this.x_Button_Search.SetBinding(Button.IsEnabledProperty, b);
}
2) When the Control raises the Unloaded event, I clear the internal bindings and un-wire any eventhandlers.
if (x_Button_Search != null)
{
this.x_Button_Search.ClearValue(Button.IsEnabledProperty);
}
This seems to be the cleanest way of ensuring that no trailing references exist between the x_Button_Search element and the Control. I don't know if this is strictly necessary.
3) Again, when the Control raises the Unloaded event, I clear bindings to existing dependency properties.
this.ClearValue(SearchParametersProperty);
If I fail to do this I can cause leaks. For example, if the SearchParameters property was bound to some INotifyPropertyChanged object then a reference to the Control remains in the PropertyChanged event on the INotifyPropertyChanged object to which I am bound even after the control has been unloaded i.e. the View will stay around as long as the Model and that may not be desired.
4) I 'flicker' the Template value so that next time the control is loaded, the template is reapplied and the OnApplyTemplate method is fired again.
var oldTemplate = this.Template;
this.Template = null;
this.Template = oldTemplate;
The reason to do 4 is that I need to reinstate bindings when the Control is reloaded onto a page. In Silverlight, there are two points of entry through which to do this: in the OnApplyTemplate override or after the control fires the Loaded event. As I want to enforce binding values before the control has been loaded (to avoid flickering), there is only one available entry point available, OnApplyTemplate. I have to flicker the template in order to force the template to reapply when the control is reloaded.
It appears this pattern up to point 3 is the bare minimum for providing garbage collected controls.
My problem comes when you want to unload your control (remove it from a Panel for example) and subsequently reload it. Any dependency properties on the control have been set to null in point 3. For example, imagine there is a binding on the declaration of the control e.g. . As far as I can tell, there is no way of reinstating this Binding once the value of SearchParameters has been set to null, it's not part of a Template after all. The result is that when the control is re-loaded it's as if the value of SearchParameters was null. So I either skip out step 3 in the pattern and get a reloadable control that is not garbage collected, or I keep 3 and get an unreloadable control.
What you do in 1) seems really strange. Why initiating a binding to the template in code and not in xaml?
We have solved lots of memory leak issues in silverlight using this software
http://memprofiler.com/
EDIT
For more control over the binding, you can use
{Binding Property, RelativeSource={RelativeSource TemplatedParent}}
That way the implicit converters are used as expected and you can also specify your own. And I believe that BindingMode TwoWay works as well.
Good luck!