我有一个 CF 应用程序,随着时间的推移会泄漏 UserControls。这花了一些时间,但我缩小了范围,甚至在完整框架(3.5)中复制了该行为。由于这两种行为都存在,我不想称其为错误,但我肯定不明白为什么会发生这种情况,希望有人能对此有所了解。
所以我创建了一个带有表单和按钮的简单 WinForms 应用程序。单击 Button 会在创建新的 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();
}
}
}
这是用户控件。它只是跟踪活动(即未完成)实例的数量。它上面只有一个标签,所以我可以直观地确认它在表格上。
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());
}
}
这里奇怪的是实例数无限增长。最终,在设备上,我的内存不足。我怀疑我也会在 PC 上,我只是不倾向于点击明年的按钮。
现在,如果我像这样更改 UserControl 的默认设计器生成的 Dispose 方法,只需添加 ReRegisterForFinalize 调用:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
if (disposing)
{
GC.ReRegisterForFinalize(this);
}
}
然后它的行为完全符合预期,在收集期间完成实例(手动或自动时)。
那么为什么会这样呢?显然基地正在调用 SuppressFinalize,但究竟为什么会发生这种情况,为什么以 Odin 的名义这是默认行为?