为什么和如何避免事件处理程序内存泄漏?
我刚刚通过阅读StackOverflow的一些问题和答案,意识到在C#中使用+=
添加事件处理程序(或者我猜,其他.net语言)会导致常见的内存泄漏。
过去我多次使用过这样的事件处理程序,从来没有意识到它们可能导致或已经导致了我的应用程序中的内存泄漏。
这是如何工作的(意思是,为什么这会导致内存泄漏)?
我该如何解决这个问题? 正在使用-=
相同的事件处理程序吗?
有处理这种情况的常见devise模式或最佳实践吗?
示例:我该如何处理具有多个不同线程的应用程序,使用许多不同的事件处理程序在UI上引发多个事件?
有没有什么好的和简单的方法在已经build成的大型应用程序中有效地进行监控?
原因很简单:当事件处理程序订阅时,事件的发布 者通过事件处理程序委托(假设委托是实例方法)持有对订阅者的引用。
如果发布者的寿命比订阅者长,那么即使没有其他用户的引用,它也会保持订阅者活着。
如果你用相同的处理程序退订事件,那么是的,这将删除处理程序和可能的泄漏。 然而,根据我的经验,这实际上很less是一个问题 – 因为通常我发现出版商和订阅者的生活时间大致相同。
这是一个可能的原因…但根据我的经验,这是相当夸张的。 你的里程可能会有所不同,当然…你只需要小心。
是的, -=
已经足够了,但是跟踪每一个分配的事件可能相当困难。 (详情请看Jon的post)。 关于devise模式,看看弱势事件模式 。
事件实际上是一个事件处理程序的链表
当你在事件上执行+ = new EventHandler时,这个特定的函数是否被添加为侦听器并不重要,它将在每个+ =时被添加一次。
当事件被引发时,它会逐个浏览链表,并调用所有添加到这个列表中的方法(事件处理程序),这就是为什么事件处理程序仍然被调用,即使页面不再运行活着(扎根),只要他们联系起来,他们就会活着。 所以他们会被调用,直到事件处理程序被取消挂钩 – =新的EventHandler。
看这里
和MSDN在这里