【发布时间】:2009-07-11 15:32:48
【问题描述】:
这是一个 C# WinForm 问题。我有一个 MDI 子窗体,当窗体打开时,它会生成许多表以显示在 DataGridView 中。表可能很大,我使用 DataBinding 将表连接到 DataGridView。当我关闭表单时,我注意到表单占用的内存被及时回收。
我使用正常的方式来显示 MDI 子窗体:
var f = new FormBigMemory(objPassedIn);
f.Show();
如此处所示,我无法显式调用表单的 Dispose() 方法。我假设当 f 超出其生命周期时,.net 将自动回收它所占用的内存。
由于表单占用大量内存,我想显式调用 GC.Collect(); (我知道这样做可能不是一个好主意)。为此,我使用以下代码更改代码以在对话框模型中显示表单:
using(var f = new FormBigMemoryDialog(objPassedIn);
{
f.ShowDialog();
}
GC.Collect();
看到表单占用的内存在调用 GC.Collect() 后没有被回收,我感到非常失望。在表单关闭并调用 GC.Collect() 后,我使用内存分析器工具获取内存快照。最大的内存由 BindingList 占用!我真的不明白:如果整个表单都被处理掉了,为什么BindingList 仍然存在于内存中。我检查了我的代码,没有任何 BindingList 引用从表单中泄露出来。
知道为什么这种有线的事情会发生在我身上吗?非常感谢任何关于 .net 内存管理的建议和技巧。
编辑:
感谢您的许多回答。让我澄清几点。
我并不是要处理 BindingList。 BindingList 在我的代码中用作数组,因此我希望看到 BindingList 持有的内存的回收。我不好不说清楚。
我明白不要自己调用 GC 操作。但就我而言,我想在表单关闭后立即明确地看到表单所占用的内存回收,无论如何要这样做?示例代码?
在我的问题中,我可以多次重复打开同一个表单,每次关闭表单时,内存消耗都会增加,直到 OutOfMemory 抛出。这显然是不对的。我期望看到的是,表单关闭后,内存回落到原来的水平,我可以在不增加内存的情况下反复打开和关闭表单。
编辑 2:
我进一步研究了代码。表单关闭后最大的数组(一个BindingList)不会被释放。它由 BindingSource 引用,而 BindingSource 由 EventHandler、CurrencyManager 和用户控件引用。 BindingSource 和用户控件都被(关闭的)表单引用,而(关闭的)表单被一些事件处理程序引用。
以上是我关闭表单后的内存快照。我使用对话框模型打开表单,关闭后调用其 Dispose() 方法,然后调用 GC.Collect() 强制回收内存。为什么在此之后表单实例仍然存在于我的内存快照中??
【问题讨论】:
-
尽量不要假设问题出在 API 上。 GC 的测试比您的代码更彻底。