I have test code like this:
public class A : CriticalFinalizerObject
{
~A()
{
File.WriteAllText("c:\\1.txt", "1z1z1");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
throw new Exception();
}
}
First I tried running it without deriving A from CriticalFinalizerObject. Finalizer wasn’t called after end of this program.
That surprised me as I thought it was more deterministic but okay. Then I’ve read about CriticalFinalizerObject’s that ensure their finalizers will be called. I derived A from it.
Guess what. It still doesn’t get executed.
What am I doing/understanding wrong?
(Please don’t write obvious stuff about garbage collector being non-deterministic, I know that. It is not the case as the program is over and I imagined I could safely clean up after a nice unhandled managed exception.)
Firstly, let’s read about CriticalFinalizerObject in MSDN, we can read, that:
The main word here is UNLOAD.
Secondly, let’s read MSDN again, this time about Exceptions in managed threads:
The main word is TERMINATION.
So, when there is an unhandled exception in main thread – app terminates, but CriticalFinalizerObject helps only on unloading of Domain.
For example, CriticalFinalizerObject can helps in such situation:
This is a situation, where domain was unloaded, and CriticalFinalizerObject guarantee you, that your finalizer will be called.
In your situation with terminating of app you can try to subscribe to
and manually finalize your objects.
UPD:
Jeffrey Richter in his book “CLR via C#” wrote about CriticalFinalizerObject, that it’s for situations where you send your code for example to SQLServer, which can run C# as a procedures. In such case CriticalFinalizerObject helps you to clean your object, if SQLServer will unload your library’s Domain.
Also CriticalFinalizerObject is for situations where you need in finalizer of object to call method of another object, because of CriticalFinalizerObject guarantee you, that it’s finalizer will be called after finalizers of all non CriticalFinalizerObject objects.