C#:如果GC需要内存,它会收集还是会发出内存不足异常?

C#:如果GC需要内存,它会收集还是会发出内存不足异常?,c#,memory-management,garbage-collection,large-object-heap,C#,Memory Management,Garbage Collection,Large Object Heap,我的代码中有一个循环,它生成许多byte[]数组(每个数组大约1到2MB),用数据填充它们,然后丢弃引用。因此,即使引用仅保留一段时间 在短时间内,我可以看到私人工作组的增长 现在,如果我尝试在循环之后分配一个大数组(~400 MB),是否会出现内存不足异常?或者分配会迫使GC收集瞬态数据吗 谢谢 这要看情况而定。您无法确定垃圾收集器是否会及时丢弃。使用字节数组是相当安全的,但是如果不使用dispose() 这会导致内存不足异常,即使您可能已放弃所有引用。 如果遇到问题,可以尝试GC.Colle

我的代码中有一个循环,它生成许多byte[]数组(每个数组大约1到2MB),用数据填充它们,然后丢弃引用。因此,即使引用仅保留一段时间 在短时间内,我可以看到私人工作组的增长

现在,如果我尝试在循环之后分配一个大数组(~400 MB),是否会出现内存不足异常?或者分配会迫使GC收集瞬态数据吗


谢谢

这要看情况而定。您无法确定垃圾收集器是否会及时丢弃。使用字节数组是相当安全的,但是如果不使用
dispose()
这会导致内存不足异常,即使您可能已放弃所有引用。

如果遇到问题,可以尝试
GC.Collect(0),尽管这通常是不可取的。

生成许多1-2MB阵列是个坏主意。即使避免了内存不足的情况,性能也会受到影响。在大型对象堆上分配许多短期对象是当前GC不能很好处理的一种分配模式

我强烈建议尽可能回收它们。实现一个池,一旦不再需要阵列,就将它们扔进池中。然后在分配第一个时,检查您是否能够满足池中的请求。这种模式在我的一个程序中带来了巨大的性能优势


我认为内存不足会强制执行GC,但如果非托管分配在同一时间发生,您仍然可以获得OOM。

如果您对此感到担心,您可以随时调用GC.Collect();在循环之后的大数组之前,这将强制所有代的垃圾收集。但是,不要在循环中进行操作,除非您不关心时间,因为这可能会非常慢(对于循环来说太慢,对于一次性操作来说就不那么慢了。)

Dispose与GC无关。Dispose在这里有什么帮助?我认为字节数组甚至没有。Dispose实际上并没有释放内存。它通常释放非托管资源。如果我没有弄错的话,使用dispose会将对象标记为已完成,从而在收集垃圾时不必运行终结器。这允许GC以更少的努力释放更多的内存。即使这是正确的,您也不必担心这一点,除非在非常特殊的情况下。“在大型对象堆上分配许多短期对象是当前GC无法很好处理的分配模式。”想在这里找到你的消息来源吗?@Andy这是我自己的经验。我有一个项目,每秒将几个屏幕截图放入阵列中,使用池重用阵列后,性能得到了很大提高。我认为原因很简单,就是您每秒分配的大量内存一直迫使GCs。对于大型对象,即使每秒分配的内存相对较少,也会分配和丢弃大量内存。我在某个地方读到LOH对象只在Gen2收集期间收集,但我不确定这一点。