我有一个主窗口,我们会调用main
和一个子窗口,我们会在child
我们的child
中使用用户控件来呼叫control
致电main
。
程序以child
开头,用户会执行一些操作来启动control
,FileSystemWatcher
其中包含FileSystemWatcher
。但是,我开始注意到child
事件在Window_Closing
关闭后仍在触发。 哦,哦。所以我开始挖......
当我为child
订阅UserControl_Unloaded
事件时,它会按预期触发。当我订阅control
的{{1}}事件时,它会按预期触发(在child
关闭后立即触发)。所以我在control
上放了一个析构函数,在main
关闭之前显然没有发生。
那么为什么我的用户控件的析构函数在卸载用户控件时没有处理属性?如果我知道哪些是相关的话,我会包含代码片段......
答案 0 :(得分:0)
好吧,在输入问题之后,StackOverflow的真棒让我看到this question,它有一个不错的通用答案。
我的解决方案是取消订阅FileSystemWatcher
事件中的所有UserControl_Unloaded
个事件。简单地将观察者对象设置为null是不够的。对于像.NET这样的托管语言来说,似乎有太多的工作,但我猜不是。
答案 1 :(得分:0)
FileSystemWatcher
实施IDisposable
。这通常表示类使用垃圾收集器无法自动(或及时)回收的非托管资源(如文件句柄或非托管内存)。 IDisposable
提供了Dispose
方法,此类可用于正确释放其非托管资源。当然,清理也可以通过其他方法完成,但IDisposable
'惯例'使程序员更容易看到哪些类需要清理。这也意味着“处理”这个词。在C#中有一个非常具体的含义。
如果FileSystemWatcher
未被处理,它看起来仍然存在。因为您没有删除这些事件处理程序,所以它仍然包含对您的用户控件的引用,因此它仍然存在,并且您继续看到引发的事件。删除事件处理程序是一个好主意(特别是当事件提升对象具有更长的生命周期时),但在这种情况下它只解决症状,而不是根本问题:它允许垃圾收集器回收用户控件,但是FileSystemWatcher
还活着。
对于析构函数(它们通常称为C#中的终结函数),很少需要它们。它们可以作为实施IDisposable
的类的最后手段 - 以防程序员忘记拨打Dispose
- 但是他们的成本很低(终结者需要在队列并且它们由特殊的终结器线程调用)并且您无法控制它们何时被执行。