cta*_*cke 6 .net c# garbage-collection
我有一个CF应用程序,随着时间的推移泄漏UserControls.花了一些时间,但我把它缩小了,甚至在完整的框架中复制了这个行为(3.5).由于两者都存在这种行为,我不想把它称为错误,但我肯定不明白为什么会发生这种情况,并希望有人能够对此有所了解.
所以我创建了一个带有Form和Button的简单WinForms应用程序.单击按钮可在创建新UserControl和Disposing该控件之间切换.非常简单.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
UserControl1 m_ctl;
private void button1_Click(object sender, EventArgs e)
{
if (m_ctl == null)
{
m_ctl = new UserControl1();
m_ctl.Visible = true;
this.Controls.Add(m_ctl);
}
else
{
this.Controls.Remove(m_ctl);
m_ctl.Dispose();
m_ctl = null;
GC.Collect();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是UserControl.它只是跟踪实时(即未定型)实例的数量.它没有任何内容,只有一个标签,所以我可以直观地确认它在表格上.
public partial class UserControl1 : UserControl
{
private static int m_instanceCount = 0;
public UserControl1()
{
var c = Interlocked.Increment(ref m_instanceCount);
Debug.WriteLine("Instances: " + c.ToString());
InitializeComponent();
}
~UserControl1()
{
var c = Interlocked.Decrement(ref m_instanceCount);
Debug.WriteLine("Instances: " + c.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
这里奇怪的是实例计数无限增长.最终,在设备上,我的内存不足.我怀疑我也会在PC上,我只是不想点击下一年的按钮.
现在,如果我改变UserControl的默认设计器生成的Dispose方法,只需添加ReRegisterForFinalize调用:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
if (disposing)
{
GC.ReRegisterForFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
然后它的行为完全符合预期,在收集期间完成实例(手动或自动时).
那为什么会这样呢?显然,基础是调用SuppressFinalize,但究竟为什么会发生这种情况,为什么以Odin的名义它是默认行为?
那么为什么会发生这种情况呢?显然基地正在调用 SuppressFinalize,但到底为什么会发生这种情况,以及为什么以奥丁的名义这是默认行为?
这是(正确)实现的类的默认行为IDisposable。当您调用 时IDisposable.Dispose,默认的建议行为是抑制终结,因为终结的主要原因是清理从未释放的资源。这是因为终结是一项昂贵的操作 - 您不想不必要地终结对象,并且如果Dispose被调用,则认为您已经清理了非托管资源。无论如何,任何托管内存都会得到处理。
您应该覆盖Dispose,并在覆盖范围内进行减量Dispose。
的文档IDisposable中对此行为进行了解释。示例Dispose方法调用实现是(来自参考文档):
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time
GC.SuppressFinalize(this);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
593 次 |
| 最近记录: |