我有显示新表单对话框的示例代码:
private void button1_Click(object sender, EventArgs e)
{
(new Form2()).ShowDialog(this);
GC.Collect();
}
如果表单有按钮,面板标签等,则执行此form2的Dispose方法,但如果我添加toolStrip,则不执行Dispose方法。为什么在这些情况下执行Dispose?
如果表格是由ShowDialog显示的话我加了我应该执行Dispose方法,但是为什么它有时没有呢?
编辑: 可以在ShowDialog之后添加Collect方法。此方法仅用于测试并多次执行。
要检查是否执行了Dispose方法,我添加了断点(在调试模式下)。当然,程序结束时会执行使用ToolStrip的示例处理。
好的,我知道如何正确实现它,因为我感兴趣的是为什么GC无法清理,如果在表单上是toolStrip?
显示它的最简单的代码是: 例1 - 结果 - 100, 实施例2 - 结果> 0(GC可以清理), 例3 - 总是0。 为什么示例2和3有所不同?
private class Form2 : Form
{
public static int disposed = 0;
byte[] data;
private System.Windows.Forms.ToolStrip toolStrip11;
public Form2(bool addToolStrip)
{
data = new byte[100000];
this.Shown += (sender, e) => { this.Close(); };
this.Controls.Add(new Button());
if (addToolStrip)
{
this.toolStrip11 = new System.Windows.Forms.ToolStrip();
this.Controls.Add(this.toolStrip11);
}
}
protected override void Dispose(bool disposing)
{
++disposed;
base.Dispose(disposing);
}
}
private void ShowResult()
{
GC.Collect(); GC.Collect();
GC.WaitForFullGCComplete();
MessageBox.Show(Form2.disposed.ToString());
Form2.disposed = 0;
}
private void button1_Click(object sender, EventArgs e)
{
//proper
for (int i = 0; i < 100; ++i)
{
using(Form2 f = new Form2(true))
{
f.ShowDialog();
}
}
ShowResult();
//ok GC can clean - why yes ?
for (int i = 0; i < 100; ++i)
{
Form2 f = new Form2(false);
f.ShowDialog();
}
ShowResult();
//GC can't clean - why not ?
for (int i = 0; i < 100;a ++i)
{
Form2 f = new Form2(true);
f.ShowDialog();
}
ShowResult();
}
答案 0 :(得分:1)
您的代码没有意义 - 在您声称泄漏内存的电话之前,您正在强制执行垃圾收集周期。
你应该只implement Dispose
to get rid of unmanaged resources。对于托管资源,尝试在任何常见用例中击败垃圾收集器是没有意义的。此外,我不确定你是怎么认为你“泄漏内存”因为你无法预测或知道GC何时正常工作 - 严格来说.NET程序只有一个如果GC 拒绝正确清理内存泄漏。由于这是未向开发人员公开的信息 - 即使是明确的清理,也可以自行决定选择不收集所有潜在的垃圾 - 根据定义,您的索赔无法核实。
答案 1 :(得分:0)
许多一次性物品也有定型器。当GC通常清理对象时,它将首先检查它是否有一个尚未运行的终结器。如果没有,它会进入队列以运行终结器,然后实际符合垃圾回收的条件。
由于这种机制,一些一次性物体可能会清理其资源,即使它们没有明确处理。
那就是说,这是一种不可靠的机制。一旦对象有资格进行收集,您不知道何时收集该对象,并且在运行终结器时该对象所处的状态可能导致与“自身”的异常和未定义的交互。
您应尽可能避免依赖终结器,而应明确处置此类可支配资源。