使用垃圾收集?

时间:2010-06-30 11:13:03

标签: c# garbage-collection dispose

我想知道在调用Dispose()方法时执行的操作。 Object在Dispose()调用或Dispose()上快速释放所有资源,标记Object已准备好进行垃圾回收。当我们将Object引用设置为NULL时发生了什么。实际上我在.NET 2.0中有Windows表单应用程序。并且我希望在经过一定时间后调用垃圾收集器(例如5分钟后)以收集所有未引用的对象。

9 个答案:

答案 0 :(得分:9)

Dispose通常为frees unmanaged resources owned by the object。调用Dispose不会触发垃圾回收;当您的对象不再引用它时,就会收集它,就像您从未调用过Dispose一样。

将对象引用设置为null只会导致该引用不再指向该对象;你通常不需要这样做(例如,你几乎不需要将局部变量设置为null)。

您自己也几乎不需要自己触发垃圾回收。您是否看到一个问题,表明您需要每5分钟运行一次垃圾收集,而不是在运行时选择的时候?

答案 1 :(得分:7)

Dispose方法没有什么神奇之处,就像任何其他方法一样。调用Dispose方法不会在后台进行任何清理或更改对象的状态,它只会执行您在方法中所做的操作。它的特殊之处在于它是在IDisposable接口中定义的,因此它是告诉对象清理其资源的标准方法。

在Dispose方法中,对象应该处理所有非托管资源,例如数据库连接和Font对象。

当您释放对象时,您不必担心任何托管资源。类似于字节数组的结构完全由垃圾收集器处理,您可以在放开时将其保留在对象中。您不需要设置对null的任何引用,当您不再使用对象时,垃圾收集器将找到删除它及其引用的任何对象的最佳时间。

垃圾收集器通常在单独使用时效果最佳,没​​有必要在收集未使用的对象时告诉它。当它应该完成时它会自己弄明白,并且通常它会比你更好,因为它可以访问大量有关内存状态和代码所没有的机器状态的信息。

您可能会觉得应该尽量减少内存使用量,但这本身并没有优势。计算机不能更好地工作,因为它有更多的可用内存。相反,如果你的代码试图进行清理,或强迫垃圾收集器做任何事情,那么当它应该忙于做更重要的事情时,它正在进行清理。如果需要,垃圾收集器将清理未使用的对象。

答案 2 :(得分:2)

如果某个对象没有对其进行引用,则该对象可以使用它。如果它在一段时间内对其进行了引用(由垃圾收集器管理),它就开始通过所谓的“世代”进行推广。

Dispose方法只是一种模式(不是语言强加的对象删除机制),表示该对象现在可以清理任何非托管资源,关闭任何连接等。

Dispose方法执行的操作完全由程序员控制,众所周知,它可能什么都不做。

垃圾收集器对Dispose方法没有兴趣 - 但是通过Finalizer,可能无论如何都会调用对象的Dispose逻辑 - 遵循IDisposable模式的人会将终结器实现为最后一个“你忘了调用Dispose了我会在GC杀死我“清理资源的方式”之前做到这一点。

请注意,如果未调用Dispose,则任何托管资源最终都将进行GC(除非保留引用)。但是,只有在整个应用程序进程完成时才会回收非托管资源(以及仍保留引用的任何托管资源)。

答案 3 :(得分:1)

这里的其他人已经充分回答了“IDisposable如何与垃圾收集器进行交互”和“何时应该问GC.Collect”部分问题。

我有一篇博文,详细介绍when you should set variables to null to help the garbage collector(问题的第三部分)。简短的回答是“几乎从不,除非它是一个静态变量。”

答案 4 :(得分:0)

自动垃圾收集的重点是您不必担心释放对象。不要试图“帮助”垃圾收集器。

对象在超出范围后最终被垃圾收集。无法手动“释放”对象或将其标记为更快的垃圾回收。请记住哪些对象在范围内(或从范围内的对象引用)。​​

Dispose方法只是一种方法。它与垃圾收集无关。 “Dispose”恰好是using语句调用的方法的名称:

using (var x = expr) { ... }

基本等同于

var x = expr;
try { ... } finally { x.Dispose(); }

答案 5 :(得分:0)

对于您的类对象,您要定义Dispose将执行的操作。您实现了包含方法Dispose的{​​{3}}接口,并且取决于实现。但通常Dispose的目的是释放资源(托管/非托管)并使对象成为GC的候选对象。

关于设置null我们可以说它没用。它只是注意到没有对象的引用,因此它成为GC的候选者,但同样不需要将null设置为GC可以发现没有引用没有那个的对象..

为了调用Collect,我们不建议(直到你有极端的需要和争论),因为GC已经过优化,以便知道Collection的正确时间。

答案 6 :(得分:0)

如果正确实施,Dispose将处置它实现IDisposable的任何托管资源,并立即释放任何非托管资源。当没有对象的引用时,对象本身将被标记为集合。通常,对象在using块中使用,并且在块的末尾自动调用Dispose方法,对象超出范围并且当时有资格进行收集。

在一般情况下,通过直接与垃圾收集器交互,您将导致比解决更多的问题。如果您认为必须这样做,则更有可能是您需要重构解决方案的信号 - 即,您的类之间存在太多耦合,导致对象保持活动的时间超过必要时间。更清洁的体系结构可以使系统更好地管理对象生命周期。

有关如何implement the IDisposable pattern的讨论,请参阅MSDN。

答案 7 :(得分:-1)

当调用Dispose()时,该对象仅标记为垃圾回收。 < - 更新:这是错误的。 Dispose()实际上并没有做任何事情,除非你或编译器调用它(当在'using'结构中使用时)。

来自MSDN -

  

在大多数情况下,垃圾收集器   可以确定最佳表演时间   一个集合,你应该让它运行   独立。有罕见的   强制收集的情况   可能会改善您的应用程序   性能。在这些情况下,你可以   通过使用来诱导垃圾收集   收集方法强制垃圾   集合

请参阅此文章 - http://msdn.microsoft.com/en-us/library/bb384155.aspx

答案 8 :(得分:-1)

如果您确实想强制使用垃圾收集:

GC.Collect();

请参阅此帖子,了解您不应该使用它的原因:

What's so wrong about using GC.Collect()?