【问题标题】:PropertyChangedEventManager - Will failing to call RemoveHandler cause a leak?PropertyChangedEventManager - 调用 RemoveHandler 失败会导致泄漏吗?
【发布时间】:2020-04-03 19:45:52
【问题描述】:

我想知道下面的代码是否会产生泄漏:Parent 类有Child 类的列表。 Child 对象使用 PropertyChangedEventManager.AddHandler 来通知聚合 Parent 对象中的属性更改。如果这些聚合实例从不调用RemoveHandler,会不会产生泄漏?

我了解the GC is based upon reachability, not reference counting,但显然PropertyChangedEventManager 正在某处维护处理程序订阅者列表。那么如果我不调用RemoveHandler,该列表如何清理?

我的代码所做的类似这样的简化版本:

public class Parent : INotifyPropertyChanged
{
    public Parent()
    {
        _children = new List<Child>();
        _children.Add(new Child(this));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public bool Value
    {
        get => _value;
        set 
        {
            _value = value;
            PropertyChanged?.Invoke(new PropertyChangedEventArgs("Value"));
        }
    }
    private List<Child> _children    
}


public class Child
{
    public Child(Parent parent)
    {
        // Will failing to undo this with RemoveHandler cause a leak?
        PropertyChangedEventManager.AddHandler(r, OnValueChange, "Value");
    }

    void OnValueChanged(object sender, PropertyChangedEventArgs e)
    {
        // Do something...
    }
}

【问题讨论】:

    标签: c# .net garbage-collection inotifypropertychanged


    【解决方案1】:

    答案是,不会。

    正如PropertyChangedEventManager (WeakEventManager) 的基本类型的名称所暗示的,所有注册到 PropertyChangedEventHandler 的处理程序都将保留为Weak References

    如你所知,

    弱引用允许垃圾收集器收集对象 同时仍然允许应用程序访问该对象。一个弱者 参考仅在不确定的时间内有效,直到 不存在强引用时收集该对象

    所以我们可以确保类引用(事件处理程序的声明实例)不会泄漏。

    RemoveHandler 将处理程序与事件分离。它从属性更改事件管理器维护的表中删除一个条目,以跟踪事件及其处理程序。

    事件管理器还有一个清理过程来清除 GC 已为其收集弱引用的目标的任何条目。

    所有这些都来自逆向工程,从:https://referencesource.microsoft.com/#windowsbase/Base/System/ComponentModel/PropertyChangedEventManager.cs

    【讨论】:

      猜你喜欢
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      • 2021-09-25
      • 2014-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多