这是一个 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 占用了!实在不明白:如果整个表单都被dispose了,为什么内存中还存在BindingList。我已经检查了我的代码,没有 BindingList 引用从表单中泄露出来的地方。
知道为什么这种有线的事情会发生在我身上吗?非常感谢有关 .net 内存管理的任何建议和技巧。
编辑:
感谢您的回答。让我澄清一些要点。
我并不是要处置 BindingList。 BindingList 在我的代码中用作数组,因此我希望看到 BindingList 持有的内存的回收。我的不好没说清楚。
我知道不能自己调用 GC 操作。但就我而言,我想在关闭表单后立即明确地看到表单占用的内存回收,无论如何要做到这一点?示例代码?
在我的问题中,我可以多次重复打开同一个表单,每次关闭表单时,内存消耗都会增加,直到抛出 OutOfMemory。这显然是不对的。我希望看到的是,在关闭表单后,内存会回落到原来的水平,我可以重复打开和关闭表单而不会(显着地)增加内存。
编辑 2:
我进一步研究了代码。最大的数组(一个BindingList)在窗体关闭后不释放。它由 BindingSource 引用,BindingSource 由 EventHandler、CurrencyManager 和用户控件引用。 BindingSource 和用户控件均由(关闭)表单引用,而(关闭)表单由某些事件处理程序引用。
上面是我关闭窗体后的内存快照。我使用对话框模型打开窗体,在关闭窗体后调用其 Dispose() 方法,之后我还调用 GC.Collect() 强制回收内存。为什么在这之后表单实例仍然存在于我的内存快照中??
最佳答案
永远不要调用 GC.Collect,除非你有充分的理由这样做。
我不知道细节,但这是我所知道的:
- 在删除所有 引用后删除某些内容。
- GC 不会尝试一次删除所有内容,它不想干扰程序运行。
- 表单很可能只是隐藏,而不是关闭。你如何关闭表单?
- 作为Mitch Wheat says , 事件处理程序可能很顽固,因为您经常忘记删除它们。
- Dispose 不会使表单从内存中删除,它会在表单内部调用一个普通方法,也许您可以在其中插入自己的清理逻辑。
关于c# - WinForm 什么时候释放它的资源? (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1113962/