委托会导致内存泄漏吗?

6

委托会导致内存泄漏吗?

我的意思是,例如,如果一个类A包含一个ADelegate,并且后者指向B类的BMethod,这是否会防止GC收集A类或B类?

如果是这样,我们如何“释放”委托(设置ADeletate = Nothing / null?)

您对此有什么评论:

//Class A Finalize, containing ADelegateInstance as ADelegate'
protected override void Finalize()
{
    ADelegateInstance = 
        (ADelegate)System.Delegate.RemoveAll(
            ADelegateInstance, ADelegateInstance);
    ADelegateInstance = null;
    base.Finalize();
}

'Class A Finalize, containing ADelegateInstance as ADelegate'
Protected Overrides Sub Finalize()
    ADelegateInstance = _ 
        CType(System.Delegate.RemoveAll(ADelegateInstance, ADelegateInstance), _ 
            ADelegate)
    ADelegateInstance = Nothing
    MyBase.Finalize()
End Sub
5个回答

10

是的,除非您取消事件的订阅,否则引用将保持活动状态:

someObject.SomeEvent -= SomeDelegate;

如果我有一个具有多个委托订阅/取消订阅的大型复杂对象,最终在此对象的Dispose中,我想要“让所有链接到此委托的内容失效”。 - serhio
1
然后您可以实现IDisposable。 - Ed S.
2
是的,那么我应该在该委托的Dispose方法中写什么呢?也许System.Delegate.RemoveAll(myDelegate, myDelegate)会有帮助? - serhio
你可以像我在示例中展示的那样去做。 - Ed S.
1
@serhio:语法几乎不是问题的重点。概念是相同的。 - Ed S.

2
据我所知,闭包/委托所引用的上下文只要闭包/委托仍被引用就可以不被垃圾回收 -- 否则它将失去其上下文。
以这个答案中的示例为例,我们可以看到委托可以在对象的上下文中引用变量inneri。因此,实际持有inneri的对象直到委托不再被引用,也就是在本例中,直到Button被垃圾回收之前都不能被垃圾回收。
for (int i = 0; i < 7; i++)
{
    var inneri = i;
    Button newButton = new Button();
    newButton.Text = "Click me!";
    newButton.Click += delegate(Object sender, EventArgs e)
    {
        MessageBox.Show("I am button number " + inneri);
    };
    this.Controls.Add(newButton);
}

相关文章:


换句话说,只要 ADelegate 指向 B,B 就不会被收集? - serhio

2

仅有一个引用是不足以导致内存泄漏的。请考虑以下情况。

如果一个线程创建了3个对象(其中 -> 表示一个引用),A -> B -> C -> A

如果A没有被线程引用,那么所有对象都将被收集。循环引用会被GC处理。

然而,这也意味着,如果一个委托包含一个对对象的引用,并且该委托与对象仍被引用,则委托函数将不会被清除。

这将给您以下结果:

A - (具有委托的对象) B - 包含函数引用的对象。

当A超出作用域时,B也会超出作用域。


1
如果A包含对B中函数的委托,则GC将不会销毁A。
每次写入“mydelegate += B.method”时,最好始终加入“mydelegate -= B.method”。
虽然这不是真正的内存泄漏,因为对象仍然可以被访问到。

0
在ASP.NET应用程序中使用了单例模式,并且由于某些原因,它订阅了控件事件。单例模式(包含对其自身的引用)不允许GC将其收集,另一方面该单例从未删除控件事件的订阅。这导致内存消耗持续增长:由于单例的现有引用,GC无法清理为处理单个请求服务的控件,因此新控件将为每个新请求创建。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接