一个对象上的垃圾收集,C#

时间:2009-03-13 20:40:48

标签: c# .net-3.5 garbage-collection

我需要处理一个对象,以便它可以释放它拥有的所有东西,但是它没有实现IDisposable,所以我不能在using块中使用它。如何让垃圾收集器收集它?

6 个答案:

答案 0 :(得分:9)

您可以使用GC.Collect()强制收集。使用它时要非常小心,因为完整的集合可能需要一些时间。最佳做法是让GC确定何时收集的最佳时间。

对象是否包含非托管资源但不实现IDisposable?如果是这样,那就是一个错误。

如果没有,它是否立即释放无关紧要,垃圾收集器应该做正确的事。

答案 1 :(得分:2)

如果它“拥有”除内存以外的任何内容,则需要修复该对象以使用IDisposable。如果它不是你控制的对象,那么值得选择不同的供应商,因为它说明了你的供应商真正了解.Net的核心。

如果它只拥有自己的记忆,即使是很多,你所要做的就是确保对象超出范围。 不要致电GC.Collect() - 这是其中一件事,如果你不得不问,你就不应该这样做。

答案 2 :(得分:2)

您无法对单个对象执行垃圾回收。您可以通过调用GC.Collect()来请求垃圾回收,但这会影响所有需要清理的对象。它也非常气馁,因为它会对后来的收藏品的性能产生负面影响。

另外,在对象上调用Dispose不会清理它的内存。它只允许对象删除对非托管资源的引用。例如,在StreamWriter上调用Dispose会关闭流并释放Windows文件句柄。在后续的垃圾收集之前,托管堆上的对象的内存不会被回收。

Chris Sells也在.NET Rocks上讨论了这个问题。我认为这是在他第一次出现时,但这个话题可能会在以后的采访中重新审视。

http://www.dotnetrocks.com/default.aspx?showNum=10

Francesco Balena的这篇文章也是一个很好的参考:

何时以及如何在C#中使用Dispose和Finalize http://www.devx.com/dotnet/Article/33167/0/page/1

答案 3 :(得分:0)

如果对象超出范围并且没有外部引用,它将被收集得相当快(可能在下一个集合中)。

答案 4 :(得分:0)

.NET中的垃圾收集是非确定性的,这意味着您无法真正控制它何时发生。你可以建议,但这并不意味着它会倾听。

告诉我们更多关于这个对象以及为什么要这样做。我们可以基于此提出一些建议。代码总是有帮助。并且取决于对象,可能存在Close方法或类似的东西。也许用法就是称之为。如果没有Close或Dispose类型的方法,您可能不希望依赖该对象,因为如果实际上它确实包含需要释放的资源,您可能会遇到内存泄漏。

答案 5 :(得分:-2)

提示: 基础知识在许多情况下, GC.Collect()或某些 IDisposal 不是很有用,特别是对于大型对象( LOH 用于 ~80kb + 对象,执行无压缩和受许多常见用例的高级碎片影响,这会导致内存不足(OOM)问题,即使可能数百 MB免费。随着时间的推移,事情变得越来越大,尽管对于LOH降级的物体来说可能不是这个尺寸(80左右kb),高度的平行度激怒这个问题仅仅是因为更多的物体在更短的时间内(并且可能实例化/释放大小不一。

数组的是此问题的常见嫌疑人(由于非特定异常以及来自运行时的断言,它通常也很难识别像“大对象堆碎片的高%”这样的东西会膨胀),遇到这个问题的代码的预测实施积极的重用策略。 < / p>

来自parallel extensions beta1 samples Systems.Collections.Concurrent.ObjectPool 中的一个帮助(遗憾的是,我没有看到过一个简单的无处不在的模式,比如一些附加的属性/扩展方法?),为大多数项目投入或重新实现它很简单,你可以分配一个生成器Func&lt;&gt;并使用Get / Put辅助方法重用前一个对象并放弃通常的垃圾收集。 专注于数组的通常就足够了,而不是单个数组元素。

如果.NET 4更新所有.ToArray()方法以包含.ToArray(T target),那将是很好的。

使用 SOS / windbg (.clopby sos mscoreei for CLRv4)来分析这类问题可能会有所帮助。考虑到这一点,当前的垃圾收集系统更像是垃圾回收(再次使用相同的物理内存),ObjectPool类似于垃圾重用。如果有人记得3 R,那么减少你的记忆使用也是一个好主意,因为性能需要;)