GC.SuppressFinalize method to suppress the finalizer
By Indranil Chatterjee
We often have cleanup code (especially for unmanaged resources) written in IDisposable.Dispose method as well as a finalizer method. Objects implementing IDisposable interface can suppress the finalizer method call for it if it is not required.
Cleanup code (especially for unmanaged resources can be written by implementing IDisposable.Dispose method or in a finalizer (often its recommended to do both as one can't be sure which gets called earlier). However, whenever a garbage collector
observes a finalizer method during a garbage collection pass, it places the object on a finalizer queue (which is polled by a separate thread to invoke finalizers on objects lying there) and skips
the collection.
So, one can say that finalizers delay the garbage collection by at least one pass.
If Dispose gets called earlier (either explicitly or as a part of a using block), one can avoid re-running the same cleanup in finalizer (moreover, it can cause error if one tries to cleanup something which has already been cleaned up). This can be done by calling GC.SuppressFinalize method.
The call GC.SuppressFinalize(this) instructs the garbage collector not call the finalizer for the current object. It's generally invoked from the implementation of IDisposable.Dispose method.
Here is a sample code demonstrating the use of SuppressFinalize in a dispose pattern:
using System;
namespace ConsoleApplication1
{
//This class can be used as a base class to wrap resources
//that require cleanup
public class MySafeResource : IDisposable
{
//Private flag that tracks if the stream has been disposed
private bool _disposed;
//Fields that require cleanup
public MySafeResource()
{
//Initialize resources (that require cleanup) here
}
public void Dispose()
{
//Dispose resources
Dispose(true);
//Suppress the finalizer call in case dispose gets called earlier.
//This prevents the garbage collector from putting this object on
//finalizer queue
GC.SuppressFinalize(this);
}
//Derived classes just need to override this method to provide their
//cleanup logic
protected virtual void Dispose(bool disposing)
{
//Check if the strem is not already disposed
if (!_disposed)
{
if (disposing)
{
//Dispose only, non-finalizer logic
}
//Place common cleanup logic to run for both Dispose and
//finalizer
//Set the fields to indicate that the resources has been
//disposed
_disposed = true;
}
}
~MySafeResource()
{
//Call Dispose with false to ensure only common cleanup logic
//runs
Dispose(false);
}
}
}
GC.SuppressFinalize method to suppress the finalizer (2538 Views)