事件委托使用时内存泄漏的问题
用C#编写事件或委托时如果处理不好会造成内存泄漏,看下面代码:
public
class
DoA2EventArgs : EventArgs
{
}
public class ClassA
{
public delegate void DoAEventHandler( object sender, EventArgs e);
public event EventHandler < DoA2EventArgs > DoA2EventHandler;
public DoAEventHandler DoAEvent;
protected void OnDoA2Event(DoA2EventArgs args)
{
EventHandler < DoA2EventArgs > handler = DoA2EventHandler;
if (handler != null )
{
handler( this , args);
}
}
public void DoA()
{
if (DoAEvent != null )
{
DoAEvent( this , new EventArgs());
}
}
public void DoA2()
{
OnDoA2Event( new DoA2EventArgs());
}
~ ClassA()
{
Console.WriteLine( " Class A Finished! " );
}
}
public class ClassB
{
ClassA a;
public ClassB()
{
a = new ClassA();
a.DoAEvent = DoA;
}
public void DoA( object sender, EventArgs e)
{
}
~ ClassB()
{
Console.WriteLine( " Class B Finished! " );
}
}
{
}
public class ClassA
{
public delegate void DoAEventHandler( object sender, EventArgs e);
public event EventHandler < DoA2EventArgs > DoA2EventHandler;
public DoAEventHandler DoAEvent;
protected void OnDoA2Event(DoA2EventArgs args)
{
EventHandler < DoA2EventArgs > handler = DoA2EventHandler;
if (handler != null )
{
handler( this , args);
}
}
public void DoA()
{
if (DoAEvent != null )
{
DoAEvent( this , new EventArgs());
}
}
public void DoA2()
{
OnDoA2Event( new DoA2EventArgs());
}
~ ClassA()
{
Console.WriteLine( " Class A Finished! " );
}
}
public class ClassB
{
ClassA a;
public ClassB()
{
a = new ClassA();
a.DoAEvent = DoA;
}
public void DoA( object sender, EventArgs e)
{
}
~ ClassB()
{
Console.WriteLine( " Class B Finished! " );
}
}
如果我们做如下实现
ClassB b
=
new
ClassB();
ClassA a = new ClassA();
a.DoAEvent = b.DoA;
a.DoA2EventHandler += new EventHandler < DoA2EventArgs > (b.DoA2);
b = null ;
GC.Collect();
ClassA a = new ClassA();
a.DoAEvent = b.DoA;
a.DoA2EventHandler += new EventHandler < DoA2EventArgs > (b.DoA2);
b = null ;
GC.Collect();
这是我们会发现,虽然对象b已经被赋值为空,但对象并没有被GC回收掉。原因是a对象还存在,同时a对象的DoAEvent
和 DoA2EventHandler 引用了b对象。
要将b回收掉我们可以做如下操作
一种方式是将a回收掉
a = null;
b = null;
这样 b 就回收掉了。
如果不想把a回收掉则
a.DoAEvent
=
null
;
a.DoA2EventHandler -= b.DoA2;
a.DoA2EventHandler -= b.DoA2;
还有一点要提一下的是
ClassB 类内部申明的 ClassA 对象,如果事件委托指向ClassB 对象本身,则不需要额外做操作,b = null; 时
ClassB 和 ClassA 实例都会自动回收。