【问题标题】:C# - Memory leak when passing an event as parameter to a subclassC# - 将事件作为参数传递给子类时的内存泄漏
【发布时间】:2014-05-22 19:23:03
【问题描述】:

在过去的几天里,我发现了我们应用程序中的内存泄漏。我知道编写此代码的开发人员的想法,但我并不真正了解泄漏发生的原因。这个想法是有一个类,其中包含一个事件。该类将实例化另一个类,该类将在 Init 方法中添加一个事件处理程序并将其删除,调用 Stop 方法。问题是,事件没有从主类中删除,并且 InvocationTargetList 正在增长和增长。 这是一个示例源代码,它显示了问题:

public class SampleEventArgs
{
    public SampleEventArgs(string s) { Text = s; }
    public String Text { get; private set; }
}

public class MainClass
{
    public delegate void SampleEventHandler(object sender, SampleEventArgs e);

    public event SampleEventHandler SampleEvent;

    public SubClass m_SubClass = new SubClass();

    public MainClass()
    {
        for (int i = 0; i < 10000; i++)
        {
            m_SubClass.Init(ref SampleEvent);
            m_SubClass.Close();
        }
        if (SampleEvent != null)
            Console.WriteLine("SampleEvent InvocationTargetList length: {0}", SampleEvent.GetInvocationList().Length);
        Console.ReadKey();
    }
}

public class SubClass
{
    public event MemoryLeakTest.MainClass.SampleEventHandler m_Subscription;

    public void Init(ref MainClass.SampleEventHandler SampleEvent)
    {
        SampleEvent += NewEvent;
        m_Subscription = SampleEvent;
    }

    public void Close()
    {
        m_Subscription -= NewEvent;
    }

    public void NewEvent(object sender, SampleEventArgs e)
    {
    }
}

好吧,我已经通过将类传递给 Init 和 Stop 方法解决了这个问题,并且还实现了 IDisposeable 模式,但我不能 100% 确定为什么上面的代码会产生内存泄漏。是不是因为将 SampleEvent 分配给 m_Suscription 会创建事件的副本,因此事件只会从 Stop 方法中的 m_Subscription 变量中删除?有什么想法吗?

【问题讨论】:

    标签: c# events memory-leaks delegates


    【解决方案1】:

    好吧,我们已经知道委托是不可变的,这就是您使用ref 参数来订阅事件的原因。

    现在仔细看看这个方法

    public void Close()
    {
        m_Subscription -= NewEvent;
    }
    

    您实际上是取消订阅一份副本,而不是来自MainClass 中的原始委托。换句话说,您只是重新分配子类中的字段,而不是主类中的字段。

    【讨论】:

    • 所以这意味着“m_Subscription = SampleEvent;”这一行创建原始委托的副本。那是我不确定的。谢谢你的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    相关资源
    最近更新 更多