I am writing a program that uses a bunch of two-way bindings, and the amount of memory used has become a huge problem. In my full application, I start with 50 MB, and then just using the bindings (i.e., changing the value on the one hand and allowing the binding to be updated on the other hand), I usually break 100 MB, although my code does not highlight anything new, My the question is what is additional memory and what can I do to control it. I created a simple, reproducible example below:
Let's say I have a main window with the following contents:
<StackPanel Height="25" Orientation="Horizontal"> <TextBox UndoLimit="1" Name="TestWidth" /> <Label>,</Label> <TextBox UndoLimit="1" Name="TestHeight" /> </StackPanel>
And then in this window constructor I create a new window, show it, and then bind its WidthProperty and HeightProperty dependency properties to variables that use INotifyPropertyChanged:
public partial class MainWindow : Window, INotifyPropertyChanged { private int _WidthInt; public int WidthInt { get { return _WidthInt; } set { _WidthInt = value; NotifyPropertyChanged("WidthInt"); } } private int _HeightInt; public int HeightInt { get { return _HeightInt; } set { _HeightInt = value; NotifyPropertyChanged("HeightInt"); } } public MainWindow() { InitializeComponent(); Window testWindow = new Window(); testWindow.Show(); Binding bind = new Binding("HeightInt"); bind.Source = this; bind.Mode = BindingMode.TwoWay; testWindow.SetBinding(Window.HeightProperty, bind);
Then, if I constantly resize the window, my memory usage in the task manager increases linearly without a visible upper limit. The program starts with 17 MB, and within 30 seconds after changing it, it increases to 20 MB and soars after a certain point in low 20 (thanks Jan). This happens even if there are no bindings and memory is not returned. Although this is annoying, it is not the βleap of memory" that I am talking about.
If I uncomment the lines that also bind text fields to variables, I get the following result: in just a few seconds it jumps from 18 MB to 38 MB, and then it floats there (note the setting of binding for the text field in XAML does not affect the splash memory). I tried to implement my own converter to bind a text field, but this does not affect memory usage.
A jump still exists if I change the variables to new dependency properties and bind to them, for example.
public static readonly DependencyProperty WidthIntProperty = DependencyProperty.Register("WidthIntProperty", typeof(int), typeof(MainWindow), new UIPropertyMetadata(0, null)); int WidthInt { get { return (int)this.GetValue(WidthIntProperty); } set { this.SetValue(WidthIntProperty, value); } } ... Binding bind = new Binding("Text"); bind.Source = TestHeight; bind.Mode = BindingMode.TwoWay; this.SetBinding(MainWindow.HeightIntProperty, bind); testWindow.SetBinding(Window.HeightProperty, bind);
or if I bind directly between the text property and the width dependency property and use BindingMode.OneWay or vice versa.
Using the CLR profiler does not seem to show me what is being allocated, and I do not have access to the commercial memory profiler. Can someone explain to me what is stored in memory, and how can I get rid of it while maintaining the functionality of a continuous BindingMode? Should I implement my own binding method and handle events myself? Or is there something I can regularly hide outside of the GC?
Thank you for your time.