【问题标题】:Why dispose an object which will surely get disposed of soon regardless?为什么要处置一个无论如何都会很快被处置的物体?
【发布时间】:2016-03-26 05:42:11
【问题描述】:

假设我有一个程序,例如单击按钮。

然后我创建了一个 Graphics 对象。

显然我应该处理掉它,例如

using(Graphics gr__=this.CreateGraphics())  {

} 

或者在 try-catch-finally 的 finally 中调用 .Dispose()

但考虑到程序很快就会结束。

假设我在过程的本地创建它(不是全局的,不是在使用中)。但在程序本地。

那么肯定和其他任何变量一样,它会在程序完成时自动处理掉,不是吗?

那么为什么手动/显式处理它对我来说很重要?

为什么我不能让它像任何其他变量一样自动进行垃圾收集?

当然它可能比'int'大一点,但它可能仍然很小,并且不会在内存中很长时间,因为无论如何过程结束得如此之快。甚至可能在使用完成或调用Dispose() 之后,过程就结束了,因此如果变量是过程的本地变量,我想它会被处理掉。那么,为什么还要为Dispose()/using 的显式垃圾收集而烦恼呢?

【问题讨论】:

  • 看起来'int'没有被垃圾回收,但是在它声明的过程完成后,其他一些内存管理会处理它。垃圾收集有时会运行,但可能不会在程序完成时运行。我认为当 C 中有指针或引用时,当你使用 malloc 时,它适用。你会释放它,这是垃圾收集,但你不会这样做一个'int;。 IDisposable 对象可能是某种不同类型的东西,需要某种不同形式的垃圾回收。

标签: c# .net winforms memory idisposable


【解决方案1】:

The Microsoft .NET class library provides a managed interface for GDI+ via the System.Drawing namespace. GDI+ 基于 C++ 并产生对非托管对象的引用。因此,处置 System.Drawing 命名空间的一次性对象很重要,因为垃圾收集器不会自动处置非管理对象。这些对象可能包含完成这项工作的终结器;但是,您无法控制何时执行这些终结器。未决的终结器也使堆变得混乱。因此,最好显式调用Dispose() 或通过using-statement 调用。

【讨论】:

  • 你能用代码证明垃圾收集器没有处理它吗?
  • 您将不得不使用内存分析工具并比较显式处理的版本和没有显式处理的版本。
【解决方案2】:

那么肯定和任何其他变量一样,它会在过程完成时自动处理,不是吗?

不幸的是,并非所有 System.Drawing 类都如此(编辑:阅读 dotctor 答案)

还有一些其他棘手的类,例如 Bitmap,虽然它是“托管的”,但大小很小。所以,每当处理晚了,就会造成内存不足!

在内存泄漏发生之前处置未使用的对象是一种更好的做法。

不过细节比较复杂。

您可以在 System.Drawing 中搜索更多非托管资源以了解更多信息。

【讨论】:

  • 不,它不会导致内存泄漏。 Graphics 的 Dispose 方法将在它完成时被调用。
  • 已编辑,我参考你的回答
【解决方案3】:

这里有两个不同的概念。

  1. 处理
  2. 垃圾收集

这两个概念有很多不同。

虽然Graphics 在被 GC 收集时会被释放,但为什么要等待 GC 运行并增加应用程序的内存占用?

这是Graphics析构函数的代码。

~Graphics()
{
  try
  {
    this.Dispose(false);
  }
  finally
  {
    // ISSUE: explicit finalizer call
    // ISSUE: explicit non-virtual call
    __nonvirtual (((object) this).Finalize());
  }
}

阅读全文

Fundamentals of Garbage Collection

what is relation between GC, Finalize() and Dispose?

What and where are the stack and heap?

【讨论】:

  • 当过程完成并 GC 其变量时不会运行 GC?我认为局部变量的一个优点是它们只存在于过程的生命周期中,因此使用的内存更少。
  • 不,不会。变量是,但分配给对象的内存存在于内存中。引用对象的变量和内存中的对象本身是有区别的。
  • int a 会不会在程序结束后内存也不清楚?我们为什么不手动释放它呢?
  • int 不是参考变量。它是一种值类型。 int 类型的局部变量使用的内存将在离开作用域后被清除(方法完成)
  • 程序完成时是否在 int 上进行垃圾收集?
【解决方案4】:

一般而言,您无法知道对象何时会被垃圾回收并被丢弃。

在处理之前,一些对象会保留对资源的引用,这些资源会占用你的内存或禁止某些操作。因此,最好在这些对象不再使用时立即处理它们。

我正在处理一个临时 SQLite 数据库文件在使用后无法删除的错误,但只是有时!经过三天令人沮丧的研究,我发现问题在于没有及时处理的 SQLite 命令对象。

所以使用你的usings ;-)

【讨论】:

    猜你喜欢
    • 2015-12-31
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多