在抛出OutOfMemoryException之前调用GC.Collect

时间:2011-01-14 05:54:38

标签: .net garbage-collection out-of-memory

有没有办法在抛出OutOfMemoryException之前调用GC.Collect()?

我想我正在寻找一种方法来执行以下代码流程:

Try to Allocate Memory
On Pass Return
Call GC.Collect()
Try to Allocate Memory
On Fail Throw New OutOfMemoryException()

我正在写一个缓存实现,目前我正在遇到内存异常,所以目前要解决它我正在使用:

If GC.GetTotalMemory(False) >= cache.CacheMemoryLimit + (100 * 1024 * 1024) Then
    // When Total Memory exceeds CacheMemoryLimit + 100MB
    GC.Collect()
End If

4 个答案:

答案 0 :(得分:5)

也许我不理解你的问题,但是你不可能只是抓住OutOfMemoryException抛出并在那里调用GC.Collect吗?将try / catch放在一个循环中,直到你完成任务并确保它能够自我清理为止。

bool isFinished = false;
while (isFinished) {
  try {
    // do operations in here
  } catch (OutOfMemoryException oom) {
    GC.Collect();
  }

  // if you're done...
  isFinished = true;
}

请原谅使用C#伪而不是VB,除非我别无选择,否则我尽量不在VB中工作。

答案 1 :(得分:5)

实际上.NET会很乐意抛出内存不足的异常,而不是垃圾收集和成功。这是我对微软.net实现的几个抱怨之一。在一个或多个线程中分配并立即丢弃大量内存的单元测试似乎已通过。然而,一旦大批老一代人超出范围,我认为问题就开始了。那些东西不会马上被拿走。

因此,例如,如果您的代码一次从磁盘上读取一百万个XmlDocuments,那么除非GC.Collect()每隔几个文档,否则您将获得OutOfMemory异常是合理的。

编辑:http://social.msdn.microsoft.com/forums/en-US/clr/thread/52a7eb17-ac05-470c-b063-a78427cd4406/

答案 2 :(得分:4)

Out of Memory异常的重点是让你知道你的内存不足,毕竟GC系统失败了。如果您真的在使用缓存系统,那么您应该考虑查看弱引用或软引用。这些允许系统在内存变紧时丢弃项目,即使它们有引用它们。

在一个缓存系统中,当你查找一个对象时,你会得到一个结果,下一秒你会得到一个NULL,因为内存足够紧,迫使系统丢弃弱引用的对象。此时,您的缓存会重新创建对象,并将其放回缓存中,然后继续前进,就好像它是您第一次引用该对象一样。

答案 3 :(得分:2)

调用GC.Collect可以修复与时序相关的OutOfMemory异常。 正如上面提到的Jugglist " .NET会很乐意抛出内存不足的异常,而不是垃圾收集和成功。" 我有一个高速软实时视频处理系统,在负载很重的情况下偶尔会抛出OutOfMemory异常。在已知的处理死区(在下一个相机触发之前)中GC.Collect调用的策略位置修复了这些问题。另外一个选择是根据需要手动处理对象,但是为什么我们使用托管环境。我的应用程序是编译x86内存模型的事实可能会加剧这个问题。因此,如果您正在做一些异常内存密集的事情,并且觉得您在代码中有一个地方,您认为进行垃圾收集是合适的,那么就这样做。 这已在此广泛讨论:What's so wrong about using GC.Collect()?