.net 代理会导致内存泄漏吗?

.net 代理会导致内存泄漏吗?,.net,memory-leaks,delegates,.net,Memory Leaks,Delegates,代理会导致内存泄漏吗 我的意思是,例如,如果一个类a包含一个ADelegate,后者指向B(属于B类)的B方法,这能阻止GC收集a类或B类吗 如果是这样,我们如何“释放”代理(设置ADeletate=Nothing/null?) 您对此有何评论: //Class A Finalize, containing ADelegateInstance as ADelegate' protected override void Finalize() {     ADelegateInstance =

代理会导致内存泄漏吗

我的意思是,例如,如果一个类
a
包含一个
ADelegate
,后者指向
B
(属于
B
类)的
B方法,这能阻止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

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

someObject.SomeEvent -= SomeDelegate;

好吧,只要闭包/委托仍然被引用,闭包/委托引用的上下文就不能被垃圾收集,否则它将丢失其上下文

举个例子,我们看到委托可以在对象的上下文中引用变量
inneri
。因此,在委托不再被引用之前(在本例中,直到
按钮
被垃圾收集之前),实际上包含
inneri
的对象不能被垃圾收集

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);
}
for(int i=0;i<7;i++)
{
var inneri=i;
按钮newButton=新按钮();
Text=“单击我!”;
newButton.Click+=委托(对象发送方,事件参数e)
{
MessageBox.Show(“我是按钮编号”+inneri);
};
this.Controls.Add(newButton);
}
相关职位:


如果A包含对B中某个函数的委托,则GC不会销毁A

每次编写“mydelegate+=B.method”时,总是输入“mydelegate-=B.method”是个好主意


虽然这不是真正的内存泄漏,因为仍然可以访问对象。

仅仅有一个引用不足以导致内存泄漏。请考虑以下内容:

如果一个线程生成了3个对象(其中->表示引用),则a->B->C->a

如果线程未引用,则收集所有。循环引用由GC处理

但是,这显然也意味着,如果委托包含对对象的引用,并且仍然引用了带有委托的对象,那么委托函数将不会被清除

这将为您提供以下信息

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


当A不在范围内时,B将返回。

在ASP.NET应用程序中使用单例时会出现这种情况。出于某种原因,它过去常常订阅控件的事件。它是单例(包含对自身的引用)这一事实不允许GC收集它,另一方面,单例从未删除对控制事件的订阅。这导致了内存消耗的永久性增长:用于为单个请求提供服务的控件,由于来自单例的现有引用而未被GC清理,为每个新请求创建的新控件。

如果我有一个包含多个委托订阅/取消订阅的大型复杂对象,最后,在Dispose of this object中,我希望“让die”指向此委托的所有链接。然后您可以实现IDisposable.yes,以及我应该在Dispose方法中为该委托编写什么内容,也许
System.Delegate.RemoveAll(myDelegate,myDelegate)
会有帮助吗?你会像我在示例中所说的那样去做。@serhio:语法不是问题的焦点。概念是一样的。换句话说,你的意思是只要ADelegate指向B,B就不会被收集?。。