我可能不理解conecept或我做错了什么。 我对.NET中的内存管理有一些疑问。
想象一下情况:
Form1
是大人物形式,因为MDI父母和一点FormChild
被绑定为孩子:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
FormChild formChild = new FormChild();
formChild.MdiParent = this;
formChild.Show();
}
}
现在,孩子正在分配一点内存作为模拟:
public partial class FormChild : Form
{
private readonly List<byte[]> _list = new List<byte[]>();
public FormChild()
{
InitializeComponent();
}
private void FormChild_Load(object sender, EventArgs e)
{
int i = 0;
while (i < 100)
{
_list.Add(new byte[1024 * 1024 * 10]);
i += 1;
}
}
}
现在,我正在使用内存分析器检查内存堆中的内容。
我明白了,如果我点击按钮,就会分配内存。然后我关闭FormChild
,然后调用Dispose()
。但内存仍然分配。如果我再次点击System.OutOfMemoryException
发生。
为什么GC等待释放托管内存? 或者这是我的设计错误?
答案 0 :(得分:3)
它看起来像某种计时问题,其中formChild的第一个实例仍然可以访问(即不是垃圾),而第二个实例是创建的。您无法容纳_list
两次。
注意我关闭FormChild并调用Dispose()是关于资源和Window句柄的声明,而不是释放内存。
目前尚不清楚你是否编写了自己的Dispose(),但在这个(相当特殊的)情况下你应该这样做。
从void Dispose(bool disposing)
文件中剪切FormChild.Designer.cs
方法并将其移至FormChild.cs
。
用它来释放巨大的内存块:
protected override void Dispose(bool disposing)
{
_list = null; // add this
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
请注意,这不是“通常”的内存管理形式,但需要它,因为您的_list也不常见。
答案 1 :(得分:0)
您可以使用GC.Collect(http://msdn.microsoft.com/en-us/library/xe0c2357.aspx)
立即执行垃圾收集但是,我通常让它自己处理并实现Dispose方法。
答案 2 :(得分:-1)
覆盖Dispose
中的FormChild
,以便您可以清理资源。
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_list != null)
{
// Clear it, dispose it, do whatever you want with it.
}
}
base.Dispose(disposing);
}
正如Yaur所说,GC在调用Dispose
时不会立即清理内存,但最好还是清理一下你的内容。