memory problem with self-removing usercontrols


I have a Windows Forms application that has a single form which is used to display several different user controls, each containing a set of controls.

Only one usercontrol is displayed at a time. 

I set up the app to create a new instance of the relevent usercontrol when it is required, adding it to the Controls collection of the form. There is then an 'OK' button on each usercontrol that removes the control from the Controls collection of the form.

The problem is that when I have the usercontrols 'self remove' in this way,  their memory does not seem to be freed up - the application just continues consuming more and more memory.

If the usercontrols are removed from the Controls collection of the form by outside code (e.g. a click event handler of a button on the form itself)  there is no memory problem - it's just when event handler code launched from within the user control itself does the remove that there is a problem.


It is quite easy to replicate the problem:

1) create a new windows forms application
2) add a usercontrol to the project
3) set the background of the usercontrol to a reasonably large image so it has some significant memory usage
4) add a button to the usercontrol
5) in the button click event handler do something like:

this.Parent.Controls.Remove(this)

6) add a button to the main form
7) in the button click event handler do something like this:

this.Controls.Add(new UserControl1())

Now run the application and click between the buttons, adding and removing instances of the usercontrol - if you monitor memory usage while doing thjis, you will see that more and more memory is consumed and never freed up.


Does anyone know what causes this problem  I assume soemthing must be preventing the garbage collector freeing up the memory used the the usercontrol instances, but I'm not sure how to work around it.

How can I have user controls 'self destruct' and remove themselves from the form without eating memory

Thanks for any help...

Dan.

 



Answer this question

memory problem with self-removing usercontrols

  • Johanvh

    In case anyone runs into this same problem, here is the solution I found.


    It turns out that this is only an issue with user controls with certain controls on them (e.g. DateTimePicker, UpDown, DomainUpDown) that register themselves with the System.Win32.UserPreferenceChanged event handler.  When the user control is removed from its parent form, this event is not unregistered, and since it is referenced by unmanged code, it prevents the garbage collector collecting the control and thus the usercontrol.


    The solution I implemented was to add a method to the base class that I use for all the user controls that loops through all its child controls (and their child controls, to take care of panels) and checks that this event is not registered.

    There is an extra complication with PrintPreviewDialog controls - I had to explicitly call the finalise() method of the control in order to ensure that the event handler registered by the UpDown control it used is removed.


    So, be careful if you have a control 'self destruct' - you may well need to do some additional cleanup work to avoid leaving objects referenced by unmanaged events and thus not garbage-collectable.

    Dan.


  • memory problem with self-removing usercontrols