在什么情况下,我们需要两次调用GC.Collect

Nit*_*dha 10 .net garbage-collection

我们有一个WPF应用程序,基于Unity和MMVVVM模式.在应用程序生命周期中,可能存在多个项目生命周期,在每个项目生命周期之后,我们执行手动拆除并尝试释放ViewModel的所有引用.对于使用Unity的事件订阅,我们使用弱引用.因此我们假设在拆除之后,我们可以调用GC Collect,以便所有垃圾对象都被垃圾收集.我们还有另一个手动取消订阅所有事件的选项,但我们更喜欢垃圾收集,因为它将为我们清除大约200MB,这将有助于新项目加载.

有一个实例,我们观察到,如果我只调用GC.Collect一次,它的引用仍然会在内存中保留一段时间.

GC.Collect();
GC.WaitForPendingFinalizers(); 
Run Code Online (Sandbox Code Playgroud)

但如果我尝试连续两次调用GC,它会很好地清理所有内容.

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)

任何想法或指示将受到高度赞赏.

更新:

Class中没有定义Finalizer.

现在我也在考虑一个案例,其中这个对象在另一个可能有终结器的对象中被引用.在我们的框架中,我们只有DBProvider的终结器,所以我不认为,即使是这种情况.

Jon*_*eet 11

听起来你有一个终结器,基本上 - 如果你只调用GC.Collect()一次,终结器正在完成,但最终的对象没有被收集.

这是否代表一个错误是另一回事.一般来说,实际上需要执行终结器并不是一个好主意,但也许在你的情况下也没关系.


Hen*_*man 6

如果我只调用GC.Collect一次,它的引用仍然会在内存中保留一段时间.

不是很奇怪.当一个对象有一个Finalizer(并且没有调用GC.SuppressFinalize())时,它会停止执行(它不会被收集,因此终结器可以使用有效对象运行).此对象引用的所有实例也会停止执行.需要通过GC进行第二轮清理.

另一方面,包含大型和复杂程序的大多数程序应该能够在不调用GC.Collect()的情况下运行.你要打两次电话......

在每个项目生命周期后,我们都会进行手动拆除

听起来很复杂,易于避免......多少refernces有没有你的域/查看模型?理想情况下,您只需剪切1或2个对"主"对象的引用而忘记它.