11

如果我有这样的方法:

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

即使它超出范围,我仍然需要在表单上调用 dispose ,这将有资格进行垃圾收集。

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

从 MSDN 看来,当不再需要表单时,您必须调用 dispose 。

4

7 回答 7

15

倾向于发生的情况是,如果项目具有纯托管资源,则不一定需要调用 dispose ,但强烈建议使用它,因为它使dispose 具有确定性。它并不总是需要(在技术意义上),因为这些托管资源现在很可能有资格进行 GC,或者默认情况下实际上没有什么可处理的,这是一个可扩展点。

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

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

也就是说,如果类型是一次性的,我总是确保调用 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)我更喜欢依赖公共合同。在这种情况下违反合同意味着我可以免受底层实现更改的影响。

于 2012-07-12T14:41:42.263 回答
4

尽管您很少需要在 C# imo 中手动处理,但您可以像这样尝试:

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

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

于 2012-07-12T14:42:35.627 回答
3

你可以简单地做:

using (var f = new Form1())
   f.ShowDialog();
于 2012-07-12T14:41:48.880 回答
3

ShowDialog 具有使 GDI 对象保持活动状态的副作用。为了避免 GDI 泄漏,我们需要适当地处理 ShowDialog。其中 Show 方法没有任何含义,GDI 会适当释放。建议处置 showDialog,不要依赖垃圾收集器。

于 2016-10-10T10:13:12.110 回答
2

如果要显式处置,请使用

 using(Form1 f = new Form1()){

            f.ShowDialog();
        }

这确保了 Dispose() 被调用,以及它立即发生

于 2012-07-12T14:42:08.303 回答
1

在您的具体示例中,不,它不太可能特别有用。表单不会占用大量资源,因此如果清理它的某些部分代码需要更长的时间,它不会导致问题。如果该表单恰好持有用于播放视频的控件,那么它实际上可能持有大量资源,并且如果您确实在 dispose 方法中处理了这些资源,那么它是值得的花时间打电话给处置。但是,对于 99% 的表单,它们的 Dispose 方法将为空,无论您是否调用它都不太可能对您的程序产生任何(或任何明显的)影响。

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

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

于 2012-07-12T15:08:27.073 回答
-1

是的,您需要并且必须调用Dispose或使用using语句,否则可以,该实例保留在内存中。

如果您将 a 放入Timer表单并在处理程序中设置断点,您可以检查它Timer.Tick。即使在没有Dispose处理程序的情况下关闭表单后也会被调用。

于 2021-09-22T17:25:43.627 回答