为Silverlight行为自动调用OnDetaching() [英] Automatically calling OnDetaching() for Silverlight Behaviors

查看:280
本文介绍了为Silverlight行为自动调用OnDetaching()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的问题是由于其中一种行为而导致存在管理内存泄漏。该行为订阅了OnAttached()覆盖中某个长寿命对象上的事件,并且应该在OnDetaching()覆盖中取消订阅该事件,以便它可以成为垃圾收集的候选对象。然而,当我从可视化树中删除控件时,OnDetaching()似乎永远不会被调用......唯一能让它发生的方法是在删除控件之前明确地分离有问题的行为,然后正确地进行垃圾收集。

现在我唯一的解决方案是在控制代码的后台创建一个公共方法,可以通过并分离任何已知行为,这会导致垃圾收集问题。在从面板中删除控件之前,需要知道要调用此代码的客户端代码。我不太喜欢这种方法,所以我正在寻找一种自动的方式来做到这一点,我忽略了或者更好的建议。

 <$ c 
foreach(Interaction.GetBehaviors(this.LayoutRoot)中的var行为)
{
behavior.Detach();
}

//继续分离控件上所有已知的有问题的行为....


解决方案

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



这是通过实施Mediator模式实现的。这个概念是,你不会给长寿命对象一个委托,引用你的 Behavior ,而是创建一个Mediator类作为中介。介体附加到长寿命对象事件并保存 WeakReference 的行为。当长寿命对象触发事件时,中介检查 WeakReference 是否仍然存在,如果是,则调用它的方法来传递事件。如果事件发生时介体发现 WeakReference 不再活动,它会将其事件处理程序从长期存在的对象中分离出来。


$ b $因此,没有什么能够阻止垃圾收集所涉及的行为和其他一切,剩下的只是一个非常小的中介实例,而死参引依然附加在长寿命对象上。由于这些介体很小,因此它们并不代表真正的问题,即使这些介质在下次事件触发时也会消失。



幸运的是,您不必构建这些东西其他人已经做到了。它被称为 WeakEventListener 。此博客:突出弱贡献;增强功能可以更轻松地防止WeakEventListener发生内存泄漏!在这个主题上有一组优秀的链接。


I am using several Blend behaviors and triggers on a silverlight control. I am wondering if there is any mechanism for automatically detaching or ensuring that OnDetaching() is called for a behavior or trigger when the control is no longer being used (i.e. removed from the visual tree).

My problem is that there is a managed memory leak with the control because of one of the behaviors. The behavior subscribes to an event on some long-lived object in the OnAttached() override and should be unsubscribing from that event in the OnDetaching() override so that it can become a candidate for garbage collection. However, OnDetaching() never seems to be getting called when I remove the control from the visual tree... the only way I can get it to happen is by explicitly detaching the problematic behaviors BEFORE removing the control and then it is properly garbage collected.

Right now my only solution was to create a public method in the code-behind for the control that can go through and detach any known behaviors that would cause garbage collection problems. It would be up to the client code to know to call this before removing the control from the panel. I don't really like this approach, so I am looking for some automatic way of doing this that I am overlooking or a better suggestion.

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

     //continue detaching all known problematic behaviors on the control....
}

解决方案

What you really need in this case is not some way to automatically detach but to ensure that the reference held by the long lived object does not keep the behaviour (and therefore everything else it has a reference to) from being garbage collected.

This is acheived by implementing a Mediator pattern. The concept is that you don't give the long-lived object a delegate with a reference to your Behaviour, instead you create a Mediator class as a go-between. The mediator attaches to the long-lived objects event and holds a WeakReference to the behaviour. When the long-lived object fires the event the mediator checks that the WeakReference is still alive, if so calls a method on it to pass on the event. If when the event occurs the mediator finds that the WeakReference is no longer alive it detaches its event handler from the long lived object.

Hence there is nothing stopping the behaviour and everything else involved from being garbage collected all thats left is a very small mediator instance with a dead reference still attached to the long-lived object. Since these mediators are tiny they don't represent a real problem and even those will disappear the next time the event fires.

Fortunately you don't have to build this stuff yourself others have already done it. It is called the WeakEventListener. This blog: Highlighting a "weak" contribution; Enhancements make preventing memory leaks with WeakEventListener even easier! has an excellent set of links on the subject.

这篇关于为Silverlight行为自动调用OnDetaching()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆