未释放事件Handler可能导致内存泄漏
http://tech.ddvip.com 2008年01月18日 社区交流
内容摘要:以前对于释放Handler的观念是一点也没有,这主要因为没此方面的意识,没有养成好的习惯。只知道当关心这个事件的时候就注册一下, 暂时不关心了就移除掉。却从来没有想到最终不移除不必要的Handler会导致此类无法被正常回收,导致不必要的内存浪费。
运行的结果如下:
虽然我们释放了对listener的引用,并且强制GC进行回收,但我们可以看到其内存占用量还是变大了,出乎了我的意料。
这就是该文作者指出的事件列表里保存的是一个强引用而非弱引用。虽然上面释放了listener变量对Listener实例的引用,但因为仍然在DisplaySettingsChanged事件列表里保存了对Listener实例的引用,导致Listener实例并不能被垃圾回收(有人引用,自然不会回收)。
那么接下来看看下面的代码:
Release Event Hanlder
class DisplaySettingsListener : IDisposable
{
byte[] m_ExtraMemory = new byte[1000000];
public DisplaySettingsListener()
{
SystemEvents.DisplaySettingsChanged += new EventHandler(ehDisplaySettingsChanged);
}
private void ehDisplaySettingsChanged(object sender, EventArgs e)
{
}
IDisposable Members#region IDisposable Members
public void Dispose()
{
SystemEvents.DisplaySettingsChanged -= new EventHandler(ehDisplaySettingsChanged);
}
#endregion
}
class Program
{
static void DisplayMemory()
{
Console.WriteLine("Total memory: {0:###,###,###,##0} bytes", GC.GetTotalMemory(true));
}
static void Main()
{
DisplayMemory();
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
Console.WriteLine("--- New Listener #{0} ---", i + 1);
DisplaySettingsListener listener = new DisplaySettingsListener();
listener.Dispose();
listener = null;
GC.Collect();
DisplayMemory();
}
Console.Read();
}
}
运行结果如下:

结果是不是正如您猜测的呢:)。已经成功地回收了listener实例。 不知为何从432944字节变到446980字节,哪位高手赐教一下啊:)
也许您觉得写这样的一个Weak Event没有必要或者显得麻烦,但您一定要记得及时地在必要的地方调用 -= 取消不再关心的事件。本文的目的也只是在此方面提个善意的提醒。
责编:豆豆技术应用
- asp.net 视频教程
- asp.net 数据库编程
- asp.net 入门教程
- ado.net 教程
- asp.net 基础讲座
- asp.net ajax 教程
- asp.net ajax 入门系列
- asp.net 控件开发基础
- asp.net 2.0 服务器控件
- asp.net 2.0 教程
- asp.net 控件开发
- asp.net 类
- asp.net 分页
- asp.net 页面缓存
- asp.net 常见问题解决
- asp.net 2.0 母版页
- asp.net SQL Server
- asp.net 错误
- asp.net 事件
- asp.net 组件
- asp.net 性能
- asp.net 文件上传
- 更多asp.net专题……