LOH的垃圾回收、弱引用和大对象

3
在我的应用程序中,我需要将大文件(约250 MB左右)加载到内存中,我采用懒加载的方式-当用户要查看文件时,我才会加载它。此后,每次用户尝试访问该文件时,我都能立即显示它,因为它已经位于内存中。 因此,问题出在垃圾回收上... 我通过WeakReference加载每个文件, 但是: 我测试了几次,我能够将大约3GB的数据加载到内存中(然后应用程序变得无法使用),但是GC没有发生。我不能调用GC.Collect(2),因为我无法确定何时调用它,那么如何告诉GC在好的时机(该死,3GB太多了...似乎GC只是没有做好工作)收集内存(弱引用)? 如何解决这个问题?我真的需要懒加载,但是当进程使用超过1GB的内存时,或者类似于此的情况下,我需要收集内存。
1个回答

1

有一个叫做GC.GetTotalMemory(bool forceFullCollection)的静态函数( http://msdn.microsoft.com/en-us/library/system.gc.gettotalmemory.aspx )。如果你已经超过了一定阈值,你可以在加载新文件到内存之前使用它来强制进行垃圾回收。

编辑:一个可能的实现

public MyFile GetMyFile(){
   if ( !is_my_file_in_memory() ) {
      if (CG.GetTotalMemory(false) > MY_THRESHOLD ) {

        GC.Collect(2);

      }
      load_my_file_in_memory();
   }
   return get_my_file_from_memory();
}

我提到过,我无法确定何时强制进行垃圾回收...在加载下一个文件后收集内存并不是一个好主意,这样就绝对没有惰性加载了。 - illegal-immigrant
我提到过,您可以在将文件惰性加载到内存之前使用此函数 :-) - linepogl
GC.GetTotalMemory(true) 在下一个文件加载之前并没有起到帮助作用...我仍然能够将大约3GB的数据加载到内存中,然后应用程序就会冻结。 - illegal-immigrant
我已经添加了一个伪实现,以确保我们谈论的是同一件事。 - linepogl
是的,我们在谈论同一件事。我也考虑过这个解决方案,但我不想在我的应用程序中创建一个限制(MY_THRESHOLD)......实际上,似乎我找到了问题的根源——一些对象从weakReference.Target获得强引用,没有释放它们! - illegal-immigrant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接