We've had problems with memory leaks in our application. I've managed to replicate one of the problems with the following simple example:
Replication setup
1) Create the following helper class which will be used to track object creation/destruction.
public class TestObject
{
public static int Count { get; set; }
public TestObject()
{
Count++;
}
~TestObject()
{
Count--;
}
}
2) Create an MDI form with three buttons, the first button will create a new MDI child as follows:
private void ctlOpenMDI_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.MdiParent = this;
newForm.Tag = new TestObject();
newForm.Show();
}
The second button will be used do the same, but with a non-MDI child form:
private void ctlOpenNonMDIForm_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.Tag = new TestObject();
newForm.Show();
}
The third button will be used to garbage collect and then display how many TestObject instances are live:
private void ctlCount_Click(object sender, EventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show("Count: " + TestObject.Count);
}
Replication steps
1) Click Open MDI form button, then close the MDI form, then click the count button. It will return Count: 1. The MDI child form and the object it references was not garbage collected - something must still have a reference to it.
Also:
Click open MDI form three times, close all 3 forms, then click the count button. It will return Count: 1. It seems as though the last closed MDI child form is not garbage collected.
Counter-cases:
1) Click Open non-MDI form, close it. Then click the count button. It will return Count: 0, the form and object have been garbage collected.
Workaround
I can workaround this problem by doing this:
Form form = new Form();
form.MdiParent = this;
form.Show();
form.Close();
Before the garbage collection. This makes this dummy form the last closed MDI child form so that the other ones can be garbage collected - but why should I have to do this? What is going on?
Also it's a bit ugly as you will get a flicker of the form opening and closing, and it seems pretty hacky too.