问题
Are finalizers guaranteed to be executed in .NET at some point (spare power outages and the like)? I know how GC works and that it is nondeterministic when exactly they\'ll run.
(The search did not display good answers, so I\'m adding this question in high expectation of a merge with the not-so-easy-to-discover actual answers. Apart from that, I already know the answer and am going to add it after a few days in case nobody mentioned it.)
回答1:
Finalizers may actually be never executed, as Raymond Chen explains. Kind of funny that this question is asked during his annual CLR week, just two days after he explained it :)
For the lazy ones, the (or rather, one) conclusion is:
A correctly-written program cannot assume that finalizers will ever run.
If you are wondering whether you can rely on finalizers, this is already everything you have to know: Don't rely on finalizers.
As Raymond Chen also states in the linked article:
Finalizers are a safety net, not a primary means for resource reclamation.
If you're looking for how to release resources, have a look at the Disposable pattern.
A finalizer may not run, for example, if:
- Another finalizer throws an exception.
- Another finalizer takes more than 2 seconds.
- All finalizers together take more than 40 seconds.
- An AppDomain crashes or is unloaded (though you can circumvent this with a critical finalizer (CriticalFinalizerObject, SafeHandle or something like that)
- No garbage collection occurs
- The process crashes
(Note: The time values may have changed over time, but were certainly true some time ago.)
I guess there are a lot more things that can cause finalizers to never run. The bottom line is, other than the quote from Mr. Chen, that finalizers are a safety net that decrease the impact of bugs, because for example resources are released sometime, which is better than never, if you forget to do it explicity.
回答2:
If a finalizer throws an exception, other finalizers will not execute.
You can also suppress finalizers if you call SuppressFinalizer on the object.
From MSDN (Object.Finalize):
The Finalize method might not run to completion or might not run at all in the following exceptional circumstances:
- Another finalizer blocks indefinitely (goes into an infinite loop, tries to obtain a lock it can never obtain and so on). Because the runtime attempts to run finalizers to completion, other finalizers might not be called if a finalizer blocks indefinitely.
- The process terminates without giving the runtime a chance to clean up. In this case, the runtime's first notification of process termination is a DLL_PROCESS_DETACH notification.
来源:https://stackoverflow.com/questions/3458177/are-net-finalizers-always-executed