У нас были проблемы с утечками памяти в нашем приложении. Мне удалось воспроизвести одну из проблем на следующем простом примере:
Настройка репликации
1) Создайте следующий вспомогательный класс, который будет использоваться для отслеживания создания / уничтожения объекта.
public class TestObject
{
public static int Count { get; set; }
public TestObject()
{
Count++;
}
~TestObject()
{
Count--;
}
}
2) Создайте форму MDI с тремя кнопками, первая кнопка создаст новый дочерний элемент MDI следующим образом:
private void ctlOpenMDI_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.MdiParent = this;
newForm.Tag = new TestObject();
newForm.Show();
}
Вторая кнопка будет использоваться для того же, но с дочерней формой не-MDI:
private void ctlOpenNonMDIForm_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.Tag = new TestObject();
newForm.Show();
}
Третья кнопка будет использоваться для сбора мусора, а затем для отображения количества живых экземпляров TestObject:
private void ctlCount_Click(object sender, EventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show("Count: " + TestObject.Count);
}
Шаги репликации
1) Нажмите кнопку Открыть форму MDI, затем закройте форму MDI, затем нажмите кнопку счета. Он вернет Count: 1. Дочерняя форма MDI и объект, на который она ссылается, не были собраны сборщиком мусора - что-то должно иметь ссылку на нее.
Также:
Нажмите три раза на открытую форму MDI, закройте все 3 формы, затем нажмите кнопку подсчета. Он вернет счетчик: 1. Кажется, что последняя закрытая дочерняя форма MDI не является сборщиком мусора.
Counter-случаи:
1) Нажмите кнопку Открыть форму без MDI, закройте ее. Затем нажмите кнопку подсчета. Он вернет Count: 0, форма и объект были собраны мусором.
Обход
Я могу обойти эту проблему, выполнив следующее:
Form form = new Form();
form.MdiParent = this;
form.Show();
form.Close();
Перед сборкой мусора. Это делает эту фиктивную форму последней закрытой дочерней MDI-формой, чтобы другие могли собирать мусор - но зачем мне это делать? Что происходит?
Кроме того, это немного уродливо, так как вы увидите мерцание открытия и закрытия формы, и это тоже кажется довольно хакерским.