代码之家  ›  专栏  ›  技术社区  ›  Dan Auclair

为Silverlight行为自动调用OnDetaching()

  •  5
  • Dan Auclair  · 技术社区  · 14 年前

    我在Silverlight控件上使用了几个混合行为和触发器。我想知道是否有任何机制可以自动分离或确保在不再使用控件(即从可视化树中移除)时调用ondetaching()来执行行为或触发器。

    我的问题是,由于某个行为,控件存在托管内存泄漏。行为订阅了OnAttached()重写中某个长寿命对象上的事件,并且应该取消订阅OnAttaching()重写中的该事件,以便它可以成为垃圾收集的候选对象。但是,当我从可视化树中移除控件时,似乎从未调用OnDetaching()。唯一的方法是在移除控件之前显式分离有问题的行为,然后对其进行适当的垃圾回收。

    现在,我唯一的解决方案是在代码背后为控件创建一个公共方法,该方法可以遍历并分离任何可能导致垃圾收集问题的已知行为。在从面板中移除控件之前,需要由客户机代码知道如何调用它。我真的不喜欢这种方法,所以我正在寻找一些自动的方式来做这件事,我忽略或更好的建议。

    public void DetachBehaviors()
    {
         foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
         {
              behavior.Detach();
         }
    
         //continue detaching all known problematic behaviors on the control....
    }
    
    2 回复  |  直到 12 年前
        1
  •  3
  •   AnthonyWJones    14 年前

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

    这是通过实现中介模式实现的。其概念是,您不会给长寿命对象一个带有对 Behaviour ,而是创建一个中介类作为中间人。中介连接到长寿对象事件,并保存 WeakReference 行为举止。当长寿命对象触发事件时,中介检查 WeakReference 仍然存在,如果是,则调用它的方法来传递事件。如果事件发生时,调解人发现 弱势群体 不再是活动的,它将其事件处理程序与长寿命对象分离。

    因此,没有什么可以阻止行为和所有其他相关的垃圾收集,剩下的只是一个非常小的中介实例,一个死引用仍然附加到长寿命对象。由于这些调解人很小,他们不代表真正的问题,甚至那些将消失在下次事件的火灾。

    幸运的是,你不必自己建造这些东西别人已经做过了。它被称为 WeakEventListener . 这个博客: Highlighting a "weak" contribution; Enhancements make preventing memory leaks with WeakEventListener even easier! 在这个问题上有一组很好的链接。

        2
  •  3
  •   Nasser    12 年前

    Joost van Schaik 提供了一种从附加行为中清除引用的替代方法,同时避免了内存泄漏的问题。这取决于使用关联对象的已加载和已卸载事件的委托执行清理工作。

    他还提供了一个代码片段,用于生成附加行为的存根。

    推荐文章