Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the Finalizer Queue and Control+ThreadMethodEntry?

I have a WindowsForms app that appears to leak memory, so I used Redgate's ANTS Memory Profiler to look at the objects I suspect and find that they are only held by objects already on the Finalizer Queue. Great, exactly what is a the Finalizer Queue? Can you point me to the best definition? Can you share any anecdotal advice?

Also, all the root GC objects on the Finalizer Queue are instances of System.Windows.Forms.Control+ThreadMethodEntry objects named "caller". I see that it is involved in multi-thread UI interaction, but I do not know much beyond that. Forgive my apparent laziness and admitted ignorance, but these resources are all buried within a vendor's component. I am talking to the vendor about these issues, but I need some direction to get me up to speed on the conversation. Can you point me to the most useful definition of ThreadMethodEntry too? Any anecdotal advice?

Also, should I even be concerned about these objects on the finalizer queue?

Update: This Red Gate article was helpful.

like image 639
flipdoubt Avatar asked Aug 12 '09 20:08

flipdoubt


People also ask

What is finalizer queue in C#?

Basically, finalization queue is an internal data structure that is controlled and managed by the GC. Hence each pointer in finalization queue points to an object that have its Finalize method call before the memory is reclaimed.

What is the function of a finalizer?

Finalizers (historically referred to as destructors) are used to perform any necessary final clean-up when a class instance is being collected by the garbage collector. In most cases, you can avoid writing a finalizer by using the System.

What kind of objects resides inside the finalization queue?

Finalization Thread The finalization queue contains entries for all the objects in the managed heap whose finalization code must run before the garbage collector can reclaim their memory.

What is Gc finalize?

Finalize method, is used to release unmanaged resources before an object is garbage-collected. If obj does not have a finalizer or the GC has already signaled the finalizer thread to run the finalizer, the call to the SuppressFinalize method has no effect.


1 Answers

The finalizer queue holds all objects that have a finalizer method defined. Recall that a finalizer is a means to collect unmanaged resources like handles. When the garbage collector collects garbage, it moves any objects with a finalizer into the finalizer queue. At some point later-- depending on memory pressure, GC heuristics, and the phase of the moon-- when the garbage collector decides to collect these objects, it walks down the queue and runs the finalizers.

Having worked with memory leaks in the past, seeing a bunch your vendor's objects in the finalizer queue could be sloppy code, but it does not indicate a memory leak. Typically, good code will expose a Dispose method that will collect both managed and unmanaged resources, and in doing so, remove themselves from the finalizer queue via GC.SuppressFinalize(). So, if the vendor's objects do implement a Dispose method, and your code doesn't call it, that could lead to a bunch of objects in the finalizer queue.

Have you tried creating a snapshot in ANTS between two points in time and comparing the objects created between them? That may help you identify any managed objects being leaked.

Also, if you want to see if the memory goes away when the finalizers are run, try this just to test with:

System.GC.Collect();
System.GC.WaitForPendingFinalizers(); // this method may block while it runs the finalizers
System.GC.Collect();

I do not recommend running this code normally. You might want to run it if you've just done a ton of work and created lots of garbage. For example, in our app, one of our functions can create about 350 MB of garbage that goes to waste after closing an MDI window. Since this is known to leave lots of garbage, we manually force garbage collection.

Also note that there is a low-level property cache in the base Windows.Forms code that will hold on to the last opened modal dialog. This could be a source of a memory leak. One sure way to get rid of this reference is to force another simple dialog to appear, then run the above GC code.

like image 137
Paul Williams Avatar answered Sep 19 '22 13:09

Paul Williams