Receiving notifications when garbage collections occur

While creating the 3rd Edition of my CLR via C# book (http://www.amazon.com/CLR-via-C-Third-Pro-Developer/dp/0735627045/ref=dp_ob_title_bk), I came up with a cool little class that will raise an event after a collection of Generation 0 or Generation 2 occurs. Here is the code for the class:

public static class GCNotification {
private static Action<Int32> s_gcDone = null; // The event’s field
public static event Action<Int32> GCDone {
add {
// If there were no registered delegates before, start reporting notifications now
if (s_gcDone == null) { new GenObject(0); new GenObject(2); }
s_gcDone +=
value;
}
remove { s_gcDone -= value; }
}
private sealed class GenObject {
private Int32 m_generation;
public GenObject(Int32 generation) { m_generation = generation; }
~GenObject() {
// This is the Finalize method
// If this object is in the generation we want (or higher),
// notify the delegates that a GC just completed
if (GC.GetGeneration(this) >= m_generation) {
Action<Int32> temp = Interlocked.CompareExchange(ref s_gcDone, null, null);
if (temp != null) temp(m_generation);
}
         // Keep reporting notifications if there is at least one delegate
// registered, the AppDomain isn’t unloading, and the process
// isn’t shutting down
if ((s_gcDone != null) &&
!
AppDomain.CurrentDomain.IsFinalizingForUnload() &&
!
Environment.HasShutdownStarted) {
// For Gen 0, create a new object; for Gen 2, resurrect the
// object & let the GC call Finalize again the next time Gen 2 is GC’d
if (m_generation == 0) new GenObject(0);
else GC.ReRegisterForFinalize(this);
}
else { /* Let the objects go away */ }
}
}
}

And here is some code to see it in action:

 

public static void Main() {
GCNotification.GCDone += g => Console.Beep(g == 0 ? 800 : 8000, 200);
var l = new List<Object>();
// Construct a lot of 100-byte objects.
for (Int32 x = 0; x < 1000000; x++) {
Console.WriteLine(x);
Byte[] b = new Byte[100];
l.Add(b);
}
}

 

This gives you a very small taste of what you should expect to see in the next edition of my book. Hope you enjoy.

 

Jeffrey Richter

View Comments

  • Cool stuff! More convenient than GC.RegisterForFullGCNotification, and lets you track Generation 0 collects as well.

  • Clever! While not very similar, I once did something like this for IDisposable's (it was actually a DisposableObject base class that just implemented a finalizer, protected Dispose(bool), and an IsDisposed property) and with #if DEBUG I included some code that let me easily check any disposables that I left hanging around without the use of a profiler.
    Looking forward to the book!

  • Hello Jeffrey.
    This is fun. I only don't get one thing: why isn't synchronization required inside add/remove, and that part where you're checking s_gcDone for null directly ("if ((s_gcDone != null) && ...")?
    P.S. Can't wait to get to your new book!

  • Nice. But is it really a notification about GC run? It looks like it happens when GenObject finalizer runs, which is a bit different (though related) event?
    Also aren't finalizable objects always get promoted to the next generation?

  • I have one query regarding how GC functions in below code:
    using system;
    using System.Threading;
    Public static class Program{
    Public static void Main() {
    Timer t = new Timer(TimerCallBack, null, 0 , 2000);
    Console.Readline();
    }
    Private static void TimerCallBack(Object o){
    Console.WriteLine("In TimerCall back" + DateTime.Now);
    GC.Collect();
    }
    }
    When i execute the above code in normal mode and debugger mode in both mode GC is not collecting the timer object. I am seeing the function being called every 2 secs. I read your book and tried to implement this. Please help me to understand the behavior of GC

  • Thank you a lot for the kind of good idea about this good topic. This is worthy to buy an essay about this post.

Recent Posts

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

6 days ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago

Mastering Compliance: The Definitive Guide to Managed Compliance Services

In the intricate landscape of modern business, compliance is both a cornerstone of operational integrity…

2 months ago