Garbage Collectionを検知する(C#)
通常のプログラミングにおいて、いつGCされたか気にする必要はありませんが、極まれにGCのタイミングで処理をしたい時があります(設計で回避するべきではありますが…)
今回はGCを検知する方法を調べてみました。
GC.WaitForFullGCComplete
GCクラスの関数を利用する方法です。
これを利用するには、App.configで下記が指定されている必要があります。(コンカレントGCを無効化)
<configuration> <runtime> <gcConcurrent enabled="false" /> </runtime> </configuration>
GCNotifierクラスを定義してみます。
GC.RegisterForFullGCNotificationで通知を有効化し、GC.WaitForFullGCApproachとGC.WaitForFullGCCompleteで通知を待ちます。
GC.RegisterForFullGCNotificationの引数は、大きいほど通知を受け取りやすくなるそうです。
static class GCNotifier { public static event Action Collected; public static void Start() { GC.RegisterForFullGCNotification(10, 10); Task.Run(() => { while (true) { GC.WaitForFullGCApproach(); if (GC.WaitForFullGCComplete() == GCNotificationStatus.Succeeded) Collected?.Invoke(); } }); } }
利用は下記のようになります。
GCNotifier.Collected += () => Console.WriteLine("collected");
GCNotifier.Start();
Finalizeを利用
下記のものを簡略化してみます。
Jeffrey Richter: Receiving notifications when garbage collections occur – Microsoft Press blog
DummyクラスのFinalizeでコールバックを呼び、さらに新しいDummyオブジェクトを生成しています。
GCNotifierクラスは下記のようになり、利用方法はGC.WaitForFullGCCompleteの時と同じです。
static class GCNotifier { public static event Action Collected; public static void Start() { new DummyObject(); } class DummyObject { ~DummyObject() { if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted) { Collected?.Invoke(); new DummyObject(); } } } }