自动为Silverlight行为调用OnDetaching()

Dan*_*air 5 silverlight garbage-collection memory-leaks attachedbehaviors expression-blend

我在silverlight控件上使用了几个Blend行为和触发器.我想知道是否有任何机制可以自动分离或确保在不再使用控件时(即从可视树中删除)为行为或触发器调用OnDetaching().

我的问题是,由于其中一个行为,控件存在托管内存泄漏.该行为在OnAttached()重写中的某个长期对象上订阅一个事件,并且应该在OnDetaching()重写中取消订阅该事件,以便它可以成为垃圾收集的候选者.但是,当我从可视树中删除控件时,OnDetaching()似乎永远不会被调用...我能够实现它的唯一方法是在删除控件之前明确地分离有问题的行为,然后正确地进行垃圾回收.

现在我唯一的解决方案是在代码隐藏中为控件创建一个公共方法,该方法可以通过并分离任何可能导致垃圾收集问题的已知行为.在从面板中删除控件之前,要由客户端代码知道调用它.我真的不喜欢这种方法,所以我正在寻找一些自动的方法,这是我忽略或更好的建议.

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*nes 3

在这种情况下,您真正​​需要的不是某种自动分离的方法,而是确保长期存在的对象所持有的引用不会阻止该行为(以及它所引用的其他所有内容)被垃圾收集。

这是通过实现中介者模式来实现的。这个概念是,您不会为长期存在的对象提供一个带有对您的引用的委托Behaviour,而是创建一个 Mediator 类作为中间人。中介者附加到长期存在的对象事件并保存对该行为的WeakReference 。当长寿命对象触发事件时,中介器检查该对象是否WeakReference仍然存在,如果是,则调用它的方法来传递事件。如果事件发生时,中介发现该对象WeakReference不再存在,它将其事件处理程序与长期存在的对象分离。

因此,没有什么可以阻止这种行为,并且涉及到被垃圾收集的所有其他内容,剩下的只是一个非常小的中介实例,其死引用仍然附加到长期存在的对象上。由于这些调解者很小,它们并不代表真正的问题,甚至这些调解者也会在下次事件触发时消失。

幸运的是,您不必自己构建这些东西,其他人已经完成了。它被称为WeakEventListener. 该博客: 强调“弱”贡献;增强功能使得使用 Wea​​kEventListener 防止内存泄漏变得更加容易!有一组关于该主题的优秀链接。