【发布时间】:2009-03-13 20:40:48
【问题描述】:
我需要处理一个对象,以便它可以释放它拥有的所有东西,但它没有实现 IDisposable,所以我不能在 using 块中使用它。我怎样才能让垃圾收集器收集它?
【问题讨论】:
标签: c# .net-3.5 garbage-collection
我需要处理一个对象,以便它可以释放它拥有的所有东西,但它没有实现 IDisposable,所以我不能在 using 块中使用它。我怎样才能让垃圾收集器收集它?
【问题讨论】:
标签: c# .net-3.5 garbage-collection
您可以使用 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),但高度的并行性加剧了这个问题,这仅仅是因为在更短的时间内有更多的对象(并且可能大小不同)被实例化/发布。
数组是这个问题的常见嫌疑人(它也经常由于非特定异常和运行时的断言而难以识别,类似“高百分比的大对象堆碎片”会膨胀),遇到此问题的代码的预后是实施积极的重用策略。
parallel extensions beta1 samples 中的 Systems.Collections.Concurrent.ObjectPool 中的一个类有帮助(不幸的是,我没有看到一个简单的普遍存在的模式,比如一些附加的属性/扩展方法?) ,对于大多数项目来说,插入或重新实现非常简单,您分配一个生成器 Func 并使用 Get/Put 辅助方法来重用您以前的对象并放弃通常的垃圾收集。 关注数组而不是单个数组元素通常就足够了。
如果 .NET 4 更新所有 .ToArray() 方法以包含 .ToArray(T 目标),那就太好了。
掌握使用 SOS/windbg (.loadby sos mscoreei for CLRv4) 来分析此类问题会有所帮助。想一想,现在的垃圾回收系统更像是垃圾回收(再次使用相同的物理内存),ObjectPool 类似于垃圾回收。如果有人记得 3R,那么出于性能考虑,减少内存使用也是一个好主意;)
【讨论】: