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

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

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

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

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

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

如果它只是拥有自己的内存,即使是很多内存,你所要做的就是确保对象超出范围。 不要调用GC.Collect() – 如果你不得不问,那就是其中之一,你不应该这样做。

您无法在单个对象上执行垃圾回收。 您可以通过调用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

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

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

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

请注意:在很多情况下, GC.Collect()或某些IDisposal 并不是很有帮助 ,特别是对于大型物体( LOH用于物体~80kb + ,不执行压实,并且对于许多物体而言会受到高度碎片化处理常见用例)这将导致内存不足(OOM)问题,即使可能有数百 MB空闲。 随着时间的推移,事情变得越来越大,尽管对于LOH降级的对象而言可能不是这个大小(80左右kb),高度的并行性会加剧这个问题,原因很简单,因为更多的对象在更短的时间内(并且可能在大小上变化)被实例化/释放。

数组是这个问题的常见嫌疑人由于非特定的exception和运行时的断言,通常很难识别 ,例如“高对象堆碎片的高百分比”会膨胀),代码受此影响的预测问题是实施积极的再利用策略。

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

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

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