Question: When Is A Good Time To Call GC.Collect()?

Answer: When you don't have enough change for the phone booth.

I'll be here all week, thank you very much. Bad pun notwithstanding, the answer to this question is pretty much never (see Rico's almost rule #1). The Garbage Collector in .NET is like a highly motivated and skilled employee. If you quit being a micro-manager ("You forgot to put the cover sheet on the TPS report") and stop looking over its shoulder, it's able to just do its job and perform quite well.

However, note that Rico says "Almost Rule #1". That must mean there are appropriate exceptions to the rule, no matter how few they may be. What are those situations? The reason I ask is I ran into the following code on the net (dramatization):

/// 
/// Stops the socket server and closes 
/// every client connection.
/// 
public void Stop()
{
    if(_isDisposed)
        throw new ObjectDisposedException(
            "SocketServer", 
            "Object is already disposed.");

    CloseConnectedClients();
    CloseListener();

    GC.Collect();
    GC.WaitForPendingFinalizers();
}

This is the Stop() method of your typical Socket Server. It closes any connected socket clients and then closes the listening thread. After that, it calls GC.Collect() and GC.WaitForPendingFinalizers(), violating Rico's almost rule. Is this perhaps one of those appropriate times to call GC.Collect()?

Typically, your socket server will have been running for a long time, so it is very likely it will have been promoted to Generation 2 and contain references to a several other Generation 2 objects. Rico points out that

If your algorithm is regularly producing objects that live to gen2 and then die shortly thereafter, you're going to find that the percent time spent in GC goes way up. Forcing more of these collects is really the last thing you wanted to do (assuming you could, note again GC.Collect() doesn't promise to do a gen2 collect).

However, this is situation is different in that the server has been around a while and calling Stop() on a server typically means you're not planning to use the Server any time soon afterwards. In fact, you're most likely about to dispose of it.

Given that, It seems to me that this might be one of those cases where calling GC.Collect() is appropriate. The goal here is a one time Generation 2 collection. Of course, there's no guarantee that a Generation 2 collect will occur. Maybe this is a situation where it makes no difference either way. Any thoughts?

For more reading:
Garbage Collector Basics and Performance Hints
Programming For Garbage Collection

What others have said

Requesting Gravatar... Ian Griffiths Aug 16, 2004 1:21 AM
# re: Question: When Is A Good Time To Call GC.Collect()?
You've constructed an argument for why it might possibly not be a really bad idea to call GC.Collect here. But I don't see any arguments as to why it might be a good idea.

Looking at this code, it looks to me like someone put some code in a finalizer to do some tidying up somewhere, and wanted to force it to run at this point...

One possible reason might be if the entire process is about to shut down. Usually the CLR gives up if all your finalizers don't manage to run within a few seconds at shutdown. Forcing a GC and then waiting for finalizers before exit would be a way of guaranteeing that all finalizers run before the process quits. (And if the process is about to shut down, most of the performance concerns probably aren't an issue any more...) So if this Stop method really is something done just before the process shuts down, then this might be the reason - it's about making sure finalizers run before the process exits.

Or it might just be totally misguided...

In general, forcing an early GC tends to promote objects that might not otherwise have got promoted which, as Rico has thoroughly documented, is a Bad Thing. You wouldn't want that to occur on a regular basis.
Requesting Gravatar... xx Jul 30, 2007 4:05 PM
# re: Question: When Is A Good Time To Call GC.Collect()?
Imports System

Namespace GCCollect_Example
Class MyGCCollectClass
Private Const maxGarbage As Integer = 1000

Shared Sub Main()
'Put some objects in memory.
MyGCCollectClass.MakeSomeGarbage()
Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(False))

'Collect all generations of memory.
GC.Collect()
Console.WriteLine("Memory used after full collection: {0}", GC.GetTotalMemory(True))
End Sub

Shared Sub MakeSomeGarbage()
Dim vt As Version

Dim i As Integer
For i = 0 To maxGarbage - 1
'Create objects and release them to fill up memory
'with unused objects.
vt = New Version()
Next i
End Sub
End Class
End Namespace
Requesting Gravatar... Ali Sep 17, 2008 2:12 PM
# Probelm regarding closing Vb.net Application
Dear sir i am working on vb.net application , when i close my application a thread is running in my task manager even when i close my application . i have builten close button for closing my application . i close my application with that cross button beside form maximize option. I have also fire form closing event and write me.dispose() and then me.close() even than my application thread keep running in my task manager . Kindly help to resolve this issue i need to break that running project thread from task manager.
reagards

What do you have to say?

(will show your gravatar)
Please add 8 and 2 and type the answer here: