【发布时间】:2014-10-23 20:27:19
【问题描述】:
在FileSystemWatcher 上注册一个事件会导致注册类保留在内存中,即使在消除了所有(我的)对FileSystemWatcher 的引用并让GC 和终结器运行之后也是如此。我在下面构建了一个示例,展示了使用 FileSystemWatcher 的对象如何保留在内存中,而使用类似事件/事件处理程序的另一组对象(A 和 B 类型)不会保留在内存中。
示例
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());
}
}
注意事项:
我知道 FileSystemWatcher 实现了
IDisposable,并且当我完成它时我应该调用Dispose()。但我的理解是,如果我错过了对Dispose()的调用,那只是意味着它需要做的工作将在终结器期间完成。有一个已知的 FileSystemWatcher 内存泄漏记录在 here。但描述听起来与我所描述的不同。
我使用 Red Gate 的 ANTS Memory Profiler 来展示是什么让它保持活力:
问题:
这是FileSystemWatcher 中的错误还是我的预期不正确?
【问题讨论】:
-
好问题。我也想得到一些专业的答案。我的假设是终结器代码必须删除对事件的引用,否则它无法清理
-
通常我使用的经验法则是,如果我使用 += 以编程方式添加处理程序,我会在使用 -= 完成时将其删除。我没有看到你在这里这样做。
标签: c# memory-leaks