Form.ShowDialog()和dispose

时间:2012-07-12 14:39:46

标签: c# winforms dispose idisposable

如果我有这样的方法:

public void Show()
{
   Form1 f = new Form1();
   f.ShowDialog();
}

我是否仍然需要在表单上调用dispose ,即使它超出范围,也可以进行垃圾回收。

从某些测试中,多次调用此Show()..在某些时候,似乎GC收集它,因为我可以看到内存尖峰然后它在某个时间点下降。

从MSDN开始,它似乎说你必须在不再需要表单时调用dispose。

6 个答案:

答案 0 :(得分:13)

如果该项目具有完全托管资源,则调用dispose不一定是必需,但 强烈建议 > 因为它使处置确定性。它并不总是需要(在技术意义上),因为那些托管资源本身现在可能符合GC的条件,或者实际上没有任何东西可以默认处理,而且它是一个可扩展点。

对于非托管资源,Dispose Pattern建议实施终结器,这将在GC上调用。如果类型没有实现终结器并且未调用dispose,则可能(很可能)资源将保持未处理状态。终结器是运行时为清理你的东西而提供的最后一次机会 - 它们也有时间限制。

注意,使GC或托管内存回收具有确定性,从C ++处理 delete。处置物品可能距离实际收集很远。但是,在托管世界中,您不关心确定性收集,只关心资源管理 - 换句话说,处理。

那就是说,如果类型是一次性的,无论是否使用托管或非托管资源,我总是确保调用Dispose或使用using语句 - 这是预期的约定:

public void Show()
{
    using (var f = new Form1())
    {
        f.ShowDialog();
    } // Disposal, even on exceptions or nested return statements, occurs here.
}

<强>更新

在与Servy讨论之后,我觉得我必须将这一点表达为我在可能的情况下处理建议背后的理由。在MemoryStream的情况下,它显然是一次性类型,但实际上并没有处理任何东西。

然而,依赖于此,依赖于MemoryStream实现。如果要将此更改为包含非托管资源,则这意味着依赖MemoryStream无法处理任何内容会成为问题。

如果可能(与IDisposable一样),我更愿意依赖公共合同。在这种情况下违反合同意味着我可以安全地避免底层实施变更。

答案 1 :(得分:4)

虽然您很少需要手动处理C#imo,但您可以这样尝试:

    public void Show()
    {
       using (Form1 f = new Form1())
       {
         f.ShowDialog();
       }
    }

然后在使用部分的最后一个荣誉中,它会自动处理掉。

答案 2 :(得分:3)

你可以这样做:

using (var f = new Form1())
   f.ShowDialog();

答案 3 :(得分:1)

如果您想明确处置,请使用

 using(Form1 f = new Form1()){

            f.ShowDialog();
        }

这确保调用Dispose(),并立即发生

答案 4 :(得分:1)

ShowDialog具有保持GDI对象存活的副作用。为了避免GDI泄漏,我们需要适当地处理ShowDialog。 Show方法没有任何含义,GDI将被适当发布。建议处理showDialog,不要依赖垃圾收集器。

答案 5 :(得分:0)

在您的具体示例中,不,它不太可能特别有用。表单不会占用大量资源,因此如果需要花费更长的时间来清除代码的某些部分,则不会导致问题。如果这种形式碰巧持有用于播放视频的控件,那么它实际上可能会占用大量资源,如果你真的在dispose方法中处理这些资源,那么它的价值花时间打电话处理。但是,对于99%的表格,他们的Dispose方法都是空的,无论你是否打电话都不会对你的程序产生任何(或任何明显的)影响。

它的主要原因是能够在1%的重要情况下处理资源。

值得注意的是,当Form关闭时,其Dispose方法已被调用。如果要在关闭表单之前处理Forms资源,则只需要添加using或显式Dispose调用。 (这对我来说听起来像是一个坏主意)。这很容易测试。只需创建一个包含两个表单的项目。让第二个表单将事件处理程序附加到Disposing事件并显示消息框或其他内容。然后,当您创建该表单的实例并显示它(作为对话框或不显示)时,您会看到当您关闭它时,即使您保持“表单”实例并且没有您,也会立即弹出消息框需要添加usingDispose来电。