【发布时间】:2025-12-05 09:25:01
【问题描述】:
我在一个循环中创建了一堆 MemoryStream 并将它们添加到一个集合(在本例中为 ArrayList)。
之后我遍历这个列表并处理这个流。
因为我遇到了 Outofmemoryexceptions,我决定改为定期处理列表并释放它。
通过list = new ArrayList() 执行此操作并没有改变内存消耗,无论是在监控它时,还是在消除内存不足异常时。甚至调用 GC.Collect() 也没有改变这一点。我注意到只有在离开范围后才释放内存。
调用List.Clear()然而,立即释放了内存并且循环按预期工作。
那么,为什么会有这种差异?这里的许多其他主题给人的印象是这两种方法应该基本相同,list = new ArrayList() 可能更有效,因为 Clear() 是一个 O(n) 操作。
我很确定没有其他对我的内存流的引用(我基本上是 list.Add(new MemoryStream(...))
【问题讨论】:
-
不是答案,而是与细节相关:*.com/questions/5358129/…
-
是否保证旧列表有 no 额外的强可达参考?代码是为 Debug 还是 Release 构建的?调试模式可能会产生比预期更长的“挂起”引用的效果,因为可能会意外地保持对旧列表的引用处于活动状态。如果是这种情况,通过 List.Clear 间接“清除”引用可能不会产生相同的效果。
-
在家里,我现在无法访问真正的代码,但我很确定我没有忽略另一个参考。但调试模式可能是罪魁祸首。无论如何,我希望 GC 在发生异常之前尽可能地完成它的工作......
-
和我一样,这就是为什么我怀疑旧的列表(或列表)以某种方式在某个地方是强可达的——这反过来又会使包含的项目保持强可达,从而阻止 GC 回收他们。如果是这种情况,那么简单地清除列表将“解决”问题,因为列表本身不再强烈引用先前的元素,即使它本身保持强可达。 (或者这可能是一个奇怪的怪事耸耸肩。)