【发布时间】:2009-10-06 16:14:09
【问题描述】:
我们的应用程序中存在内存泄漏问题。我已经设法通过以下简单示例复制了其中一个问题:
复制设置
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 个表单,然后点击计数按钮。它将返回 Count: 1。似乎最后关闭的 MDI 子窗体没有被垃圾回收。
反例:
1) 点击打开非MDI表单,关闭它。然后单击计数按钮。它将返回 Count: 0,表单和对象已被垃圾回收。
解决方法
我可以通过这样做来解决这个问题:
Form form = new Form();
form.MdiParent = this;
form.Show();
form.Close();
在垃圾收集之前。这使得这个虚拟表单成为最后一个关闭的 MDI 子表单,以便其他表单可以被垃圾收集 - 但我为什么必须这样做?怎么回事?
而且它有点难看,因为你会看到表单打开和关闭的闪烁,而且看起来也很hacky。
【问题讨论】:
标签: c# winforms forms memory-leaks mdichild