4
votes

I'am working on an application that has problems with its memory consumption. If a user clicks long enough in the application it ends in an OutOfMemoryException.

I profiled the application with 'ANTS Memory Profiler' quite a long time and in my opinion there is no 'classical' memory leak (e.g. event handlers that prevent an object from being garbage collected).

But all objects that remain in memory have one thing in common - they use, directly or indirectly - a standard .NET control (e.g. TextBox, Numberbox) that implements a Finalizer. In the 'ANTS Memory Profiler Instance Retention Graph', I can see that the only instance that holds a reference to the controls is the .NET Finalizer Queue.

Link the retention graph (I have not enough reputation to post images directly :-)) --> http://i50.tinypic.com/2d6r6nn.png

Therefore I investigated into the direction of a deadlock in the Finalizer Thread (cf. http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/) but could not find an indication for a deadlock. Also, what is against the deadlock-theory is, that after a Memory Snapshot with the Memory Profiler, which triggers a GC.Collect(), the views are garbage-collected - respectively their Finalizers are executed and everything is fine.

So, this looks like the normal lifecycle of a .net object with Finalizer, right? But in my application I can click until a OutOfMemoryException and the Garbage Collector never runs!

The last try to handle the problem was to use GC.AddMemoryPressure(), because in the views are a lot of bitmaps that allocate quite a lot of unmanaged code. But also this could not provoke the Garbage Collector to collect the free memory.

So, I think there is something intrinsically wrong with a concept in the application, which prevents the GC from freeing the memory, but I have absolutely no idea what.

Has anyone undergone similar experiences and has any clue?

Best regards

Andi

3
Your problem is likely with bitmaps not being collected because they have long living references. Could you show us the code of the bitmap stuff.user7116

3 Answers

3
votes

OutOfMemoryException sometimes lies. Sometimes it means "I can't get an unmanaged handle" - it is not quite always actually related to memory. The problem is that it is often hard to tell why something fails, and "out of memory" is probably a reasonable guess.

It sounds like a lot of things haven't been disposed promptly. Disposing them would have called their custom code to eagerly and proactively release their undamaged handles.

GC, conversely, is mainly triggered by memory pressure. These days, a PC can have lots of memory left, but run out of unmanaged handles.

0
votes

In MODEL-VIEW-VIEWMODEL (MVVM) it could be possible to cleanup objects as controls explicit if you're working with special thirdparty references. Perhaps you just need to include object.Dispose and object = null

When to dispose ViewModel in MVVM Light

0
votes

Could be a lot of things

This is just one oddity that caused an out of memory for me

In set check for = value and if so return.

Look for unnecessary calls to NotifyPropertyChanged.
I had a case where I was loading up an ObservableCollection via the public property and it was queuing up multiple NotifyPropertyChanged and that caused an out of memory.
Then I loaded up the private variable and just called NotifyPropertyChanged once when done and it fixed the out of memory.