I would be happy if someone will be able to answer the following question.
recently I was investigating memory leaks & handles problem during my work. I have seen a very strange phenomenon: I have a class that exposes only static methods. on one of the methods I do the following things
- I create an start thread
- The ThreadStart delegate calls a method that call GC.Collect() & GC.WaitForPendingFinalizers().
Most of the time the new thread never finishes it's work because it gets stuck in GC.WaitForPendingFinalizers(). The only scenario that this thread is resumed is when I activate another GC collection from my program's console menu.
The whole phenomenon doesn't happen if I make the following changes:
- I use gcThread.IsBackground = false; on the thread that invokes the GC
- I use gcThread.Join() in the method that creates this thread.
I have tried to reproduce the problem with some toy example but I couldn't.
- Can somebody explain my mistake
- Is this a GC bug
- Can somebody reproduce the problem with some toy application
Thanks in advance

Yet another GC question
ruiner333
d__i___o
If your handle count is increasing, this suggests that perhaps there is some place in your code where you are creating disposable objects but you're not calling Dispose.
Increasing handle counts are not a symptom of a problem with GC. They are a symptom of a problem in code. (The GC is not designed to free handles. It is concerned only with memory. If you are relying on the GC to free handles or other non-memory resources, then that's a bug in your code.) The only sense in which this might be a symptom of a GC problem is that it indicates you're relying on the GC to do something it (a) wasn't designed to do (free handles) and (b) does a really bad job of.
The GC does not track handle counts. It only tracks the use of memory on the managed heap. That is all. So if you have 1000 objects each of which takes up 40 bytes on the managed heap, the CLR treats that as 40,000 bytes of memory usage. It makes no difference whether it's just plain memory and data, or whether each of these objects contains a handle to something that costs 10K per object (making the total cost 10,040,000 bytes) the CLR only cares about the managed heap. Anything else is your problem.
(Strictly speaking in .NET 2, they added some features where objects could indicate to the CLR that they were exerting a hidden memory pressure. But in general, the CLR is only concerned with its own heap.)
What sorts of objects are you creating in your application Do you know what these handles are Whatever they are, the fact that you're relying on the GC and finalization to free them up for you means you are in a bad place. This isn't what the GC is for, and you'll never get this approach to work properly. (Except for trivial examples, perhaps.) You need to make sure you are calling Close or Dispose on whatever objects you're using that are wrapping external resources. This is why C# (and VB.NET v2) has the 'using' construct.
(This is a fundamental issue with garbage today's collected systems. Java has exactly the same issue - try writing a web app that doesn't call 'close' on its JDBC connection objects and see how far you scale before you run out of DB connections and grind to a halt...)
Also, a more general rule in .NET is: if you're writing a finalizer, you're almost certainly doing the wrong thing. Finalizers are only necessary in a tiny fraction of cases. (Worse than that, finalizers turn out only to be useful in a tiny fraction of the cases where they might initially seem to be useful, which is itself a tiny fraction of overall cases...)
It's not quite true to say that you should never write a finalizer, but it's so close to the truth that you should always regard the use of a finalizer with extreme suspicion. In a code review I'd approach a finalizer in much the same way I'd approach a goto statement: I'd want an astonishingly good reason for it to be there.
Baji Prasad
Itzhak,
What code is in your objects' finalizers If there is code in there that will not return (blocks, loops forever, etc), then the call to WaitForPendingFinalizers will not return.
As Peter pointed out, you probably shouldn't have a thread that calls GC.Collect like that. What problem are you trying to solve
-Chris
Atul Kulkarni
Ying06
Why are you calling WaitForPendingFinalizers if that's the last thing your thread does This will block the thread until the finalizers have run. It won't actually expedite the execution of those finalizers.
Finalizers run when the finalizer thread is good and ready to run them. This usually happens fairly promptly because the finalizer thread runs with higher than default priority.
WaitForPendingFinalizers just blocks until the queue of finalizable objects has been emptied by the finalizer thread. It has no impact on how soon the finalizer thread attempts to empty the queue. So if your thread is as you described it - you just call GC.Collect and then GC.WaitForPendingFinalizers - there's no real point in the WaitForPendingFinalizers. The only call that actually has an effect is GC.Collect.
As for why it's getting stuck, how exactly are you determining this What are you using to detect that it has not completed
In any case, I'm not sure how much value there is in firing off a separate thread to do this. The GC will suspend all the threads for some time anyway. (As I understand it, even a concurrent GC can only parallelize certain aspects of the GC process - certain stages still require all threads to be suspended.)
I've tried to repro what you describe with a toy app and I can't, so it must be something peculiar to your app. Are you making much use of finalizers
JuliusY
Hi Ian,
Thanks for your help. I understand what you say. Generally, you are right.
Best regards,
Itzhak
Anand Raman - MSFT
Hi
Thanks in advance