GC.Collect() not collecting immediately?
In the course of a discussion in chat, I wrote this console application.
Code:
using System;
class Program
{
static void Main(string[] args)
{
CreateClass();
Console.Write("Collecting... ");
GC.Collect();
Console.WriteLine("Done");
}
static void CreateClass()
{
SomeClass c = new SomeClass();
}
}
class SomeClass
{
~SomeClass()
{
throw new Exception();
}
}
Result:
Collecting... Done
Unhandled Exception: System.Exception: Exception of type 'System.Exception' was
thrown.
at SomeClass.Finalize()
I would have expected the app to crash before Done
was printed.
I don't care much about how to make it. My question is, why doesn't it?
Objects with finalizers cannot be collected within a single garbage collection procedure. Such objects are moved to f-reachable
queue, and remain there until finalizers are called. Only after that they can be garbage-collected.
Following code is better, but you should not rely on it anyway:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Also, throwing exceptions in finalizer seems too brutal for me, even for testing purposes.
Also, interesting side-effect of finalizers: an object with finalizer can still 'resurrect' itself (effectively prevent garbage collection of itself), if stores this
reference in finalizer (assigns it to some static variable).
Did you read the documentation?
Use this method to try to reclaim all memory that is inaccessible.
It is not a command, it is a request, which may or may not work out as you would like. This is not often a good idea anyway (sometimes many, many small, short-lived objects are created as a result of some process, in which case it may be beneficial to call GC.Collect
, but this is rare).
Since it doesn't seem like you are trying to solve a real problem and are instead toying around with the GC this is the best advice I have to offer.