FileSystemWatcher memory leak even after launching Finalizer
Registering for an event FileSystemWatcher
does not force the registration class to stay in memory even after all (my) references to FileSystemWatcher
and allowed to run GC and finalizers. I have provided an example below, showing how the using object FileSystemWatcher
stays in memory and another set of objects (such as A
and B
) that use similar events / event handlers do not stay in memory.
Example
class Program
{
class UsesFileWatcher
{
public FileSystemWatcher fw;
public UsesFileWatcher()
{
fw = new FileSystemWatcher(@"C:\", "*.txt");
fw.Changed += eventHandler;
fw.EnableRaisingEvents = true;
}
void eventHandler(object sender, FileSystemEventArgs e)
{
}
}
// For Comparison, I have classes A and B which use similar events and event handlers
class A
{
public event EventHandler AEvent;
}
class B
{
public A a;
public B()
{
a = new A();
a.AEvent += eventHandler;
}
void eventHandler(object sender, EventArgs e)
{
}
}
static void Main(string[] args)
{
var weakRefToB = WeakReferenceToB();
var weakRefToUsesFileWatcher = WeakReferenceToUsesFileWatcher();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("B Alive = {0}", weakRefToB.IsAlive);
Console.WriteLine("UsesFileWatcher Alive = {0}", weakRefToUsesFileWatcher.IsAlive);
Console.ReadKey();
}
static WeakReference WeakReferenceToB()
{
return new WeakReference(new B());
}
static WeakReference WeakReferenceToUsesFileWatcher()
{
return new WeakReference(new UsesFileWatcher());
}
}
Notes:
-
I understand what FileSystemWatcher implements
IDisposable
and what I should be callingDispose()
when I'm done with it. But I understand that if I miss the callDispose()
, it simply means that the work it needed to do will be done later during the finalizer. -
There is a known FileSystemWatcher memory leak documented here . But the description is different from what I am describing.
-
I used Red Hat ANTS Memory Profiler to show that it supports it:
Question:
Is this an error in FileSystemWatcher
, or my expectations incorrect?
source to share
Of course, this is not a mistake. You can directly see in the profiler that the object is being referenced. There's a system type that has a root code that has a callback that it has in FSW making it accessible from the root object.
It will remove those callbacks when it is removed, allowing it to be collected, so you will need to dispose of it if you want it to be eligible for collection.
source to share