未释放事件Handler可能导致内存泄漏

豆豆网   技术应用频道   2008年01月18日  【字号: 收藏本文

内容摘要:以前对于释放Handler的观念是一点也没有,这主要因为没此方面的意识,没有养成好的习惯。只知道当关心这个事件的时候就注册一下, 暂时不关心了就移除掉。却从来没有想到最终不移除不必要的Handler会导致此类无法被正常回收,导致不必要的内存浪费。

  以前曾看见过这样一个问题:托管代码会不会导致内存泄漏。自己对GC的了解也不是很深,但还是比较赞成这样的观点:托管代码不会产生内存泄漏,除非你没有正确释放非托管资源。

  今天看到一个非常有趣的例子,关于没有释放事件的Handler导致的内存泄漏。

  以前对于释放Handler的观念是一点也没有,这主要因为没此方面的意识,没有养成好的习惯。只知道当关心这个事件的时候就注册一下, 暂时不关心了就移除掉。却从来没有想到最终不移除不必要的Handler会导致此类无法被正常回收,导致不必要的内存浪费。

  事情是这样的,今天在看项目Source Code的时候发现一个有趣的字眼:"WeakEvent". 自己以前对WeakReference有点了解,所以就好奇地看看这是个啥玩意。

  发现其是一种通过弱引用实现的Delegate。因为没有太多的注释,所有不知其为啥用此种方式来封装事件。于是顺手Google了一下,找到了一篇关于weak event的非常有意思的文章。

  文章里提出了一个问题,场景如下:

UnRelease Event Handler
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
  
namespace ConsoleApplication16
{
  class DisplaySettingsListener
  {
    byte[] m_ExtraMemory = new byte[1000000];
  
    public DisplaySettingsListener()
    {
      SystemEvents.DisplaySettingsChanged += new EventHandler(ehDisplaySettingsChanged);
    }
  
    private void ehDisplaySettingsChanged(object sender, EventArgs e)
    {
    }
  }
  
  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 = null;
        GC.Collect();
  
        DisplayMemory();
      }
      Console.Read();
    }
  
  }
}

责编:豆豆技术应用

正在加载评论...