取消后,C#仍然挂钩了一个事件
我目前正在调试一个包含内存泄漏的大型(非常大的!)C#应用程序.它主要使用
Winforms作为GUI,尽管在WPF中制作了几个控件并使用ElementHost进行托管.到目前为止,我发现许多内存泄漏是由事件没有解开(通过调用 – =)引起的,我已经能够解决问题了.
但是,我刚遇到了类似的问题.有一个名为WorkItem(短期)的类,它在构造函数中注册到另一个名为ClientEntityCache(long long)的类的事件.这些事件从来没有被解开,我可以在.NET Profiler中看到WorkItem的实例在不应该因为这些事件而保持活着状态.所以我决定使WorkItem实现IDisposable,并在Dispose()函数中以这种方式取消事件: public void Dispose() { ClientEntityCache.EntityCacheCleared -= ClientEntityCache_CacheCleared; // Same thing for 10 other events } 编辑 这是我用于订阅的代码: public WorkItem() { ClientEntityCache.EntityCacheCleared += ClientEntityCache_CacheCleared; // Same thing for 10 other events } 我还更改了取消注册的代码,以便不调用新的EntityCacheClearedEventHandler. 编辑结束 我在使用WorkItem的代码中的适当位置调用了Dispose,当我调试时,我可以看到该函数真正被调用,而且我做 – =对于每个事件.但是我仍然得到内存泄漏并且我的WorkItems在Disposed之后仍然存活,并且在.NET分析器中我可以看到实例保持活动,因为事件处理程序(如EntityCacheClearedEventHandler)仍然在它们的调用列表中有它们.我试图解开它们不止一次(倍数= =)只是为了确保它们不会被钩住多次,但这没有用. 任何人都知道为什么会这样或者我能做些什么来解决问题? 谢谢! 编辑: 如果这有帮助,这是.NET Profiler描述的根路径: 解决方法
可能是多个不同的委托函数连接到事件.希望以下小例子能让我更清楚地了解我的意思.
// Simple class to host the Event class Test { public event EventHandler MyEvent; } // Two different methods which will be wired to the Event static void MyEventHandler1(object sender,EventArgs e) { throw new NotImplementedException(); } static void MyEventHandler2(object sender,EventArgs e) { throw new NotImplementedException(); } [STAThread] static void Main(string[] args) { Test t = new Test(); t.MyEvent += new EventHandler(MyEventHandler1); t.MyEvent += new EventHandler(MyEventHandler2); // Break here before removing the event handler and inspect t.MyEvent t.MyEvent -= new EventHandler(MyEventHandler1); t.MyEvent -= new EventHandler(MyEventHandler1); // Note this is again MyEventHandler1 } 如果在删除事件处理程序之前中断,则可以在调试器中查看调用列表.如下所示,有2个处理程序,一个用于MyEventHandler1,另一个用于MyEventHandler2方法. 现在两次删除MyEventHandler1之后,MyEventHandler2仍然被注册,因为只有一个委托,它看起来有点不同,它不再显示在列表中,但是直到MyEventHandler2的委托被删除它仍然会被事件引用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |