In my experience it seems that most people will tell you that it is unwise to force a garbage collection but in some cases where you are working with large objects that don\
However, if you can reliably test your code to confirm that calling Collect() won't have a negative impact then go ahead...
IMHO, this is similar to saying "If you can prove that your program will never have any bugs in the future, then go ahead..."
In all seriousness, forcing the GC is useful for debugging/testing purposes. If you feel like you need to do it at any other times, then either you are mistaken, or your program has been built wrong. Either way, the solution is not forcing the GC...
Not sure if it is a best practice, but when working with large amounts of images in a loop (i.e. creating and disposing a lot of Graphics/Image/Bitmap objects), i regularly let the GC.Collect.
I think I read somewhere that the GC only runs when the program is (mostly) idle, and not in the middle of a intensive loop, so that could look like an area where manual GC could make sense.
Not sure if it is a best practice...
Suggestion: do not implement this or anything when unsure. Reevaluate when facts are known, then perform before/after performance tests to verify.
The best practise is to not force a garbage collection.
According to MSDN:
"It is possible to force garbage collection by calling Collect, but most of the time, this should be avoided because it may create performance issues. "
However, if you can reliably test your code to confirm that calling Collect() won't have a negative impact then go ahead...
Just try to make sure objects are cleaned up when you no longer need them. If you have custom objects, look at using the "using statement" and the IDisposable interface.
This link has some good practical advice with regards to freeing up memory / garbage collection etc:
http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
I would like to add that: Calling GC.Collect() (+ WaitForPendingFinalizers()) is one part of the story. As rightly mentioned by others, GC.COllect() is non-deterministic collection and is left to the discretion of the GC itself (CLR). Even if you add a call to WaitForPendingFinalizers, it may not be deterministic. Take the code from this msdn link and run the code with the object loop iteration as 1 or 2. You will find what non-deterministic means (set a break point in the object's destructor). Precisely, the destructor is not called when there were just 1 (or 2) lingering objects by Wait..().[Citation reqd.]
If your code is dealing with unmanaged resources (ex: external file handles), you must implement destructors (or finalizers).
Here is an interesting example:
Note: If you have already tried the above example from MSDN, the following code is going to clear the air.
class Program
{
static void Main(string[] args)
{
SomePublisher publisher = new SomePublisher();
for (int i = 0; i < 10; i++)
{
SomeSubscriber subscriber = new SomeSubscriber(publisher);
subscriber = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(SomeSubscriber.Count.ToString());
Console.ReadLine();
}
}
public class SomePublisher
{
public event EventHandler SomeEvent;
}
public class SomeSubscriber
{
public static int Count;
public SomeSubscriber(SomePublisher publisher)
{
publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
}
~SomeSubscriber()
{
SomeSubscriber.Count++;
}
private void publisher_SomeEvent(object sender, EventArgs e)
{
// TODO: something
string stub = "";
}
}
I suggest, first analyze what the output could be and then run and then read the reason below:
{The destructor is only implicitly called once the program ends. } In order to deterministically clean the object, one must implement IDisposable and make an explicit call to Dispose(). That's the essence! :)
One case I recently encountered that required manual calls to GC.Collect()
was when working with large C++ objects that were wrapped in tiny managed C++ objects, which in turn were accessed from C#.
The garbage collector never got called because the amount of managed memory used was negligible, but the amount of unmanaged memory used was huge. Manually calling Dispose()
on the objects would require that I keep track of when objects are no longer needed myself, whereas calling GC.Collect()
will clean up any objects that are no longer referred.....