我需要处理一个对象以释放它所拥有的一切,但它没有实现IDisposable,因此我不能在using块中使用它。我该如何让垃圾回收器将其收集?
我需要处理一个对象以释放它所拥有的一切,但它没有实现IDisposable,因此我不能在using块中使用它。我该如何让垃圾回收器将其收集?
http://www.dotnetrocks.com/default.aspx?showNum=10
这篇由Francesco Balena撰写的文章也是一个很好的参考资料:.NET 中的垃圾回收是非确定性的,这意味着您无法真正控制它何时发生。您可以建议,但这并不意味着它会听从。
告诉我们更多关于对象以及为什么您想要这样做的信息。我们可以根据此提出一些建议。代码总是有帮助的。根据对象的不同,可能会有一个 Close 方法或类似的方法。也许使用方式就是调用它。如果没有 Close 或 Dispose 类型的方法,您可能不想依赖该对象,因为如果它确实包含需要释放的资源,那么您可能会遇到内存泄漏问题。
请注意:在许多情况下,碎片化可能会带来问题,在处理大型对象(LOH 用于 ~80kb+ 的对象,执行无压缩并且针对许多常见用例存在高度的碎片化)时,GC.Collect() 或一些 IDisposal 并不是非常有用,这可能会导致内存不足 (OOM)问题,即使有数百MB可用。随着时间的推移,事物会变得越来越大,尽管对于被限制在 LOH 中的对象大小可能没有达到这个程度(80kb左右),高度的并行度加剧了这个问题,因为实例化/释放的对象数量更多,时间更短(而且大小可能会有所变化)。
数组是这个问题的罪魁祸首(由于运行时的非特定异常和断言,很难识别),建议对受此问题影响的代码实施积极的重用策略,如果能看到“大量大对象堆碎片”这样的信息就更好了。
在并行扩展beta1示例中,Systems.Collections.Concurrent.ObjectPool类对于帮助一些项目重用对象(不幸的是我还没见过像附加属性/扩展方法这样简单普及的模式?)足够简单,可以轻松地投入使用或重新实现,只需分配一个生成器Func<>并使用Get/Put辅助方法来重用之前的对象和避免通常的垃圾回收。通常只需关注数组而非单个数组元素。
如果.NET 4更新所有.ToArray()方法以包括.ToArray(T target),那就太好了。
熟悉使用SOS/windbg (.loadby sos mscoreei逐步分析此类问题会有所帮助。考虑到目前的垃圾回收系统更像是垃圾再循环(再次使用相同的物理内存),ObjectPool类类似于垃圾重复利用。如果有人记得三R原则,减少内存使用也是提高性能的好方法;)