WPF memory allocation uses binding, InotifyPropertyChanged and dependent properties jump

I am writing a program that uses a lot of two-way binding, and the amount of memory used has become a huge problem. In my complete application, I start with 50Mb, and then, Just by using binding (i.e. changing the value on one side and letting the binding update the other side), I usually break 100Mb even if my code does not assign any new ones. My question is what this extra memory is and what can I do What to control it. I created a simple, reproducible example below:

Suppose I have a main window with the following content:

p>





Then in the constructor of this window, I generate a new window, display it, and then Bind its WidthProperty and HeightProperty dependency properties to variables using 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; NotifyP ropertyChanged("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);
//bind.Converter = new convert();
//this.TestHeight.SetBinding(TextBox.TextProperty , bind);

bind = new Binding("WidthInt");
bind.Source = this;

bind.Mode = BindingMode.TwoWay;
testWindow.SetBinding(Window.WidthProperty, bind);
//bind.Converter = new convert();
//this.TestWidth.SetBinding(TextBox.TextProperty, bind);
}

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(string sProp)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(sProp));
GC.Collect();
}
}

Then, if I keep adjusting the window size, my memory usage in the task manager will increase linearly without an obvious upper limit. The program starts at 17Mb and is in 30 seconds of resizing Inside it increases to 20Mb and hovering after a certain point in the lower 20 (thanks to Ian). This happens even if there is no binding, and the memory will not drop again. Although annoying, it is not what I call “memory” Jump”.

If I uncomment the line that also binds the text box to the variable, I get the following result: in a few seconds it jumps from 18Mb to 38Mb and then hovering there (please note that the Setting the binding of the text box in XAML will not affect the memory soaring). I tried to implement my own converter for the text box binding, but this will not affect the memory usage.

If I change the variable For new dependency properties and bind to them, the jump still exists, 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 the text property directly And width dependency property, and use BindingMode.OneWay or vice versa.

Using the CLR analyzer doesn’t seem to show what I’m allocating, and I can’t access the commercial memory analyzer. Can someone explain the memory to me What is retained in and how to get rid of it while still having the continuous BindingMode function? Do I have to implement my own binding method and handle the event by myself? Or can I flush out of the GC regularly?

Thank you for your time.

Remember to use such a simple program One thing is that a small amount of code will end up taking up a considerable amount of WPF infrastructure. For example, with a single TextBox, you can use the layout engine, attribute engine, template system, style system, and accessibility. The moment you start typing, You will also introduce input systems, typography support, and some non-trivial internationalization infrastructure.

The last two may be a large part of what you see in this particular example. WPF automatically utilizes There are many OpenType font features, which requires it to do a lot of work behind the scenes. (Actually, the default UI font doesn’t actually do a lot of it with it, but you still end up finding the code for the code that Segoe UI is not a very interesting font. The price.) This is a relatively expensive feature to say how subtle the difference it makes. Again, it’s surprising how significant it is for locale-aware input processing-get exactly the right i8n support in the right situation It’s more work than most people think.

You might end up paying a price for each subsystem, because TextBox is not the only WPF that uses them. Therefore, try to avoid their manual construction solutions. The effort required may end up with nothing.

The tiny test application paints a misleading picture – in actual applications, the price paid is better shared. Your first TextBox may 30MB has been spent, but you have now paged a whole bunch of things that other applications will use. If you start using an application that only uses ListBox, you can add a TextBox and compare the difference in memory consumption with the ListBox-only baseline. This might give you a rather different picture of the marginal cost of adding a TextBox to an application.

So, outside of the context of a simple test application, writing your own text box is required The work of may make a small difference to the private working set in practice. You will almost certainly end up paging in all the features and systems I mentioned in the first paragraph, because TextBox is not the only one in WPF that uses them Stuff.

Can each of these systems be more frugal? No doubt they can, but unfortunately, WPF doesn’t have as much engineering input as I thought, the distraction of Silverlight, not to mention the rumors that another attempt at the UI framework is about to appear in Win8. Unfortunately. Yes, high memory usage is a feature of WPF. (Although keep in mind that WPF applications will also use more memory on computers with more memory. Some memory is required before its working set is driven to the most efficient level Pressure.)

I am writing a program that uses a lot of two-way binding, and the amount of memory used has become a huge problem. In my complete application, I started with 50Mb, and then, just by using binding (i.e. changing the value on one side and letting the binding update the other side), I usually break 100Mb, even if my code does not assign any new ones. My problem is this extra What memory is and what I can do to control it. I created a simple, reproducible example below:

Suppose I have a main window with the following content:

p>





Then in the constructor of this window, I generate a New window, display it, and then bind its WidthProperty and HeightProperty dependency properties to variables using INotifyPropertyChanged:

public partial class MainWindow: Window, INotifyPropertyChanged
{
private int _WidthInt;
public int WidthInt
{
get {return _WidthInt; }
set {_WidthInt = value; NotifyPropertyChanged("WidthInt"); }
}

pr ivate int _HeightInt;
public int HeightInt
{
get {return _HeightInt; }
set {_HeightInt = value; NotifyPropertyChanged("HeightInt"); }
}< br />
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);
//bind.Converter = new convert();
//this.TestHeight.SetBinding(TextBox.TextProperty, bind);

bind = new Binding("WidthInt");
bind.Source = this;

bind.Mode = BindingMode.TwoWay;
testWindow.SetBinding(Window.WidthProperty, bind);< br /> //bind.Converter = new convert();
//this.TestWidth.SetBinding(TextBox.TextProperty, bind);
}

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(string sProp)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(sProp));
GC.Collect();
}
}

Then if I keep resize the window , My memory usage in task manager will increase linearly without obvious upper limit. The program starts at 17Mb, and within 30 seconds of resizing it increases to 20Mb and hovering after a certain point lower 20 (thanks to Ian ). This happens even if there is no binding, and the memory will not drop again. Although annoying, it is not what I call “memory jump”.

If I uncomment it will also change the text box Bind to the variable line, I get the following result: in a few seconds it jumped from 18Mb to 38Mb and then hovered there (please note that setting the binding of the text box in XAML will not affect the memory soaring). I tried as The textbox binding implements my own converter, but this does not affect the memory usage.

If I change the variables to the new dependency properties and bind to them, the jump is still there, 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 the text property directly And width dependency property, and use BindingMode.OneWay or vice versa.

Using the CLR analyzer doesn’t seem to show what I’m allocating, and I can’t access the commercial memory analyzer. Can someone explain the memory to me What is retained in and how to get rid of it while still having the continuous BindingMode function? Do I have to implement my own binding method and handle the event by myself? Or can I flush out of the GC regularly?

Thank you for your time.

One thing to keep in mind when using such a simple program is that a small amount of code will eventually take up quite a bit. A lot of WPF infrastructure. For example, with a single TextBox, you can use the layout engine, attribute engine, template system, style system, and auxiliary functions. At the moment you start typing, you will also introduce an input system, typography support, and some non- Trivial internationalization infrastructure.

The last two may be a large part of what you see in this particular example. WPF automatically takes advantage of many OpenType font features, which requires it to do it behind the scenes A lot of work. (Actually, the default UI font doesn’t actually do much to it, but you still end up finding out for the code that Segoe UI is not a very interesting font for the price of the code.) This is a relatively expensive feature to say What a subtle difference it makes. Again, it’s amazing how meaningful input processing for locale perception is – getting the fully correct i8n support under the correct conditions is more work than most people think.

You may end up paying a price for each subsystem, because TextBox is not the only WPF that uses them. Therefore, the effort required to try to avoid them to manually build solutions may end up with nothing.

< p>The tiny test application paints a misleading picture-in real applications, the price paid is better shared. Your first TextBox may have spent 30MB, but you are now paged Lots of things that other applications will use. If you start using an application that only uses ListBox, you can add a TextBox and compare the difference in memory consumption with the ListBox-only baseline. This might give you a rather different picture, explaining The marginal cost of adding a TextBox to an application.

So, outside the context of a simple test application, the work required to write your own text box may in practice result in a private working set Small differences. You will almost certainly end up pagination in all the features and systems I mentioned in the first paragraph, because TextBox is not the only thing in WPF that uses them.

In these systems Can each of them be more frugal? No doubt they can, but unfortunately, WPF doesn’t have as much engineering input as I thought, the distraction of Silverlight, not to mention the rumors that another attempt at the UI framework is about to appear in Win8. Unfortunately. Yes, high memory usage is a feature of WPF. (Although keep in mind that WPF applications will also use more memory on computers with more memory. Some memory is required before its working set is driven to the most efficient level Pressure.)

Leave a Comment

Your email address will not be published.