为什么.NET垃圾回收器从未被调用?

4
我正在处理一个应用程序,它存在内存消耗问题。如果用户在应用程序中长时间点击,就会出现OutOfMemoryException。
我使用 "ANTS Memory Profiler" 对应用程序进行了相当长的分析,我认为没有经典的内存泄漏(例如,事件处理程序防止对象被垃圾回收)。
但是,所有留在内存中的对象都有一个共同点-它们直接或间接使用标准的.NET控件(例如TextBox、Numberbox),这些控件实现了Finalizer。在 "ANTS Memory Profiler Instance Retention Graph" 中,我可以看到唯一持有对控件引用的实例是 .NET Finalizer Queue。
链接保留图(我没有足够的声望直接发布图片 :-)) --> http://i50.tinypic.com/2d6r6nn.png 因此,我调查了Finalizer线程死锁的方向(参见http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/),但是没有发现死锁的迹象。而且,与死锁理论相反的是,在使用Memory Profiler进行内存快照后,触发GC.Collect()后,视图被垃圾回收 - 或者说它们的Finalizers被执行,一切都很好。

所以,这看起来像是带有Finalizer的.NET对象的正常生命周期,对吧?但在我的应用程序中,我可以点击直到OutOfMemoryException,而垃圾收集器从未运行过!

最后尝试解决问题的方法是使用GC.AddMemoryPressure(),因为视图中有许多位图,分配了相当多的非托管代码。但即使这样也无法促使垃圾收集器收集空闲内存。

因此,我认为应用程序中的某些概念存在内在错误,阻止了GC释放内存,但我绝对不知道是什么。

是否有人经历过类似的经历,并有任何线索?

最好的问候

Andi


你的问题可能是由于位图具有长期引用而未被收集。你能否向我们展示一下位图相关的代码? - user7116
3个回答

3
OutOfMemoryException有时会误导人,有时它的意思是“我无法获取非托管句柄”,实际上并不完全与内存有关。问题在于往往很难确定失败的原因,“内存不足”可能是一个合理的猜测。
听起来好像许多东西没有得到及时处理。释放它们将调用它们的自定义代码,积极主动地释放它们未损坏的句柄。
相反,GC主要由内存压力触发。现在,一台计算机可以还剩很多内存,但却用尽了非托管句柄。

0

0

可能有很多事情。

这只是一个奇怪的问题,导致我内存不足。

在集合中检查=值,如果是,则返回。

寻找不必要的NotifyPropertyChanged调用。
我曾经遇到过这样的情况:通过公共属性加载ObservableCollection,它会排队多个NotifyPropertyChanged,从而导致内存不足。
然后我加载了私有变量,并在完成时仅调用了一次NotifyPropertyChanged,这解决了内存不足问题。


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