C# 未注册的事件处理程序导致内存泄漏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/448197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unregistered event handlers cause memory leak
提问by Joseph Anderson
I'm maintaining a web application that has a memory leak.
我正在维护一个存在内存泄漏的 Web 应用程序。
Based on my investigation using Red Gate ANTS memory profiler I'm pretty sure that the memory leak is caused by event handlers in the business layer.
根据我使用 Red Gate ANTS 内存分析器的调查,我很确定内存泄漏是由业务层中的事件处理程序引起的。
There's a collection that registers an event handler on each item that's added so that the collection can re-sort when the item's date is changed. It appears that this event handler is the culprit.
有一个集合在每个添加的项目上注册一个事件处理程序,以便在项目的日期更改时集合可以重新排序。看来这个事件处理程序是罪魁祸首。
The business layer for this application is quite complicated, so keeping the collection and its items in memory drags a bunch of other objects with it.
此应用程序的业务层非常复杂,因此将集合及其项保存在内存中会拖拽一堆其他对象。
I've implemented IDisposable on the collection and removed the event handlers in the Dispose method:
我已经在集合上实现了 IDisposable 并删除了 Dispose 方法中的事件处理程序:
p.OnPunchDateChanged -= this.OnPunchDateChanged;
However, implementing IDisposable doesn't help since I can't wrap all the references to the collection in using or try/catch blocks. This collection is used by portions of the application that I don't have control over.
但是,实现 IDisposable 无济于事,因为我无法在 using 或 try/catch 块中包装对集合的所有引用。该集合由我无法控制的应用程序部分使用。
How can I clear these event handlers to resolve this memory leak?
如何清除这些事件处理程序以解决此内存泄漏问题?
回答by Simon Hughes
First off, just to prove the point, try logging the adding and removal of events to a simple text file. Then, check how many were added vs removed.
首先,为了证明这一点,尝试将事件的添加和删除记录到一个简单的文本文件中。然后,检查添加和删除了多少。
It sounds as if there is a bug somewhere in the business logic which is not unregistering the event in all circumstances.
听起来好像业务逻辑中的某个地方存在一个错误,它不会在所有情况下都取消注册事件。
回答by munissor
The Dispose method on the collection should be called directly by your code because the event holds a reference to the collection. Your collection will never be destroyed by garbage collector.
集合上的 Dispose 方法应该由您的代码直接调用,因为该事件持有对集合的引用。您的集合永远不会被垃圾收集器销毁。
You should also change the behaviour of the Remove and Clean methods of the collection to detach the event handler from the removed items.
您还应该更改集合的 Remove 和 Clean 方法的行为,以将事件处理程序与已删除的项目分离。