gpt4 book ai didi

C# - 将事件作为参数传递给子类时发生内存泄漏

转载 作者:行者123 更新时间:2023-11-30 22:06:08 24 4
gpt4 key购买 nike

在过去的几天里,我追踪到了我们应用程序中的内存泄漏。我知道编写这段代码的开发人员的想法,但我并不真正了解为什么会发生泄漏。这个想法是有一个类,其中包含一个事件。该类将实例化另一个类,该类应将事件处理程序添加到 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 变量中删除?有什么想法吗?

最佳答案

好吧,我们已经知道委托(delegate)是不可变的,这就是为什么您使用 ref 参数来订阅事件。

现在仔细看看这个方法

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

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

关于C# - 将事件作为参数传递给子类时发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23815505/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com