一、事件引起的内存泄露

  1、不手动注销事件也不发生内存泄露的情况

  我们经常会写EventHandler += AFunction; 如果没有手动注销这个Event handler类似:EventHandler –= AFunction 有可能会发生内存泄露。

    public class Program
{
static void ShowMemory()
{
Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);
} static void Main(string[] args)
{
ShowMemory();
for (int i = 0; i < 5; i++)
{
EventSample es = new EventSample();
es.ShowComplete += es.MyEventHandler;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
ShowMemory();
}
Console.ReadKey();
}
} public class EventSample
{
byte[] m_ExtraMemory = new byte[1024 * 1024 * 12]; //定义一个事件
public event EventHandler ShowComplete; //触发事件
public void OnShowComplete()
{
//判断是否绑定了事件处理方法,null表示没有事件处理方法
if (ShowComplete != null)
{
//像调用方法一样触发事件
ShowComplete(this, new EventArgs());
}
} //事件处理方法
public void MyEventHandler(object sender, EventArgs e)
{
Console.WriteLine("谁触发了我?" + sender.ToString());
}
}

  上述代码输出如下:

  

  从输出来看,内存被GC正常地回收,没有问题。

  2、内存泄露的情况

  我们来将代码改动一下

    public class Program
{
static void ShowMemory()
{
Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);
} static void Main(string[] args)
{
ShowMemory();
for (int i = 0; i < 5; i++)
{
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(new MyMethod().SystemEvents_DisplaySettingsChanged);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
ShowMemory();
}
Console.ReadKey();
}
} public class MyMethod
{
byte[] m_ExtraMemory = new byte[1024 * 1024 * 12];
public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e){ }
}

  输出结果如下:

  

  从输出结果来看,内存已不能被GC正常回收。为什么会出现这种情况呢?我们来看看Microsoft.Win32.SystemEvents.DisplaySettingsChanged的源代码(省略前后部分):

    public sealed class SystemEvents
{
... ...
public static event EventHandler DisplaySettingsChanged
... ...
}

  为什么会有差别,根本区别在于后者有个SystemEvents.DisplaySettingsChanged事件,而这个事件是静态的。

  3、释放资源

  如果我们希望释放资源,则我们需要在某个地方实现-=AFunction操作

    public class Program
{
static void ShowMemory()
{
Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);
} static void Main(string[] args)
{
ShowMemory();
for (int i = 0; i < 5; i++)
{
using (MyMethod myMethod = new MyMethod())
{
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(myMethod.SystemEvents_DisplaySettingsChanged);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
ShowMemory();
}
Console.ReadKey();
}
} public class MyMethod : IDisposable
{
byte[] m_ExtraMemory = new byte[1024 * 1024 * 12];
public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) { } public void Dispose()
{
Microsoft.Win32.SystemEvents.DisplaySettingsChanged -= new
EventHandler(SystemEvents_DisplaySettingsChanged);
}

}

  输出如下:

  

  增加了一个Dispose来实现 "-="功能就OK了。

二、注意静态、单例

  静态对象生命周期很长,永远不会被GC回收,一旦被他给引用上了,那就不可能释放了。上面的例子就是被静态的DisplaySettingsChanged 引用导致不能被回收。

  另外一个要注意的是Singleton单例模式实现的类,他们也是static的生命周期很长,要注意引用链,你的类是否被它引用上,如果在它的引用链上,就内存泄露了。

C# 内存泄露的更多相关文章

  1. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  2. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  3. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  4. 基于HTML5的WebGL应用内存泄露分析

    上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...

  5. android:布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!

    1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...

  6. js内存泄露的几种情况详细探讨

    内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...

  7. 使用Xcode7的Instruments检测解决iOS内存泄露

    文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 作为一名iOS开发攻城狮, ...

  8. 使用Visual Leak Detector for Visual C++ 捕捉内存泄露

    什么是内存泄漏? 内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段 ...

  9. java内存溢出和内存泄露

    虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 最近在网上搜集了一些资料,现整理如下: —————————————————————————————————————— ...

  10. java内存泄露

    上一篇提到的是java垃圾回收,今天谈谈java的内存泄露. 首先谈下java的内存管理机制: 在Java程序中,我们通常使用new为对象分配内存,而这些内存空间都在堆(Heap)上. public ...

随机推荐

  1. Qt实现基于G.729A(G729A)的语音聊天

    一.G.729协议简介G.729协议是由ITU-T的第15研究小组提出的,并在1996年3月通过的8Kbps的语音编码协议.G.729系列主要有以下几种:G.729—最基本的G.729标准协议,原始版 ...

  2. 关于PowerShell中的命令的别名

    cmdlets的别名,有利于使用传统的cmd的方式 或者使用 bash的方式的人员,更加方便的使用使用频率较高的命令. 以下是从 别名中获取的内置的别名. PS C:\> Get-Alias * ...

  3. How to find friends

    How to find friends 思路简单,编码不易 1 def check_connection(network, first, second): 2 link_dictionary = di ...

  4. 读论文系列:Nearest Keyword Search in XML Documents中使用的数据结构(CT、ECT)

    Reference: [1]Y. Tao, S. Papadopoulos, C. Sheng, K. Stefanidis. Nearest Keyword Search in XML Docume ...

  5. python学习之路-9 socket网络编程

    socket基础 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. so ...

  6. ajaxFileUpload SyntaxError: syntax error

    在使用ajaxFileUpload上传文件时,Chrome没问题,IE和Firefox出错,Firefox报SyntaxError: syntax error错误 JS代码例如以下: $.ajaxFi ...

  7. [Immutable.js] Exploring Sequences and Range() in Immutable.js

    Understanding Immutable.js's Map() and List() structures will likely take you as far as you want to ...

  8. iOS开发CoreAnimation解读之二——对CALayer的分析

    iOS开发CoreAnimation解读之二——对CALayer的分析 一.UIView中的CALayer属性 1.Layer专门负责view的视图渲染 2.自定义view默认layer属性的类 二. ...

  9. MP3文件结构及解码概述

    MP3文件结构概述 Layer-3音频文件.MPEG(MovingPicture Experts Group)在汉语中译为活动图像专家组,特指活动影音压缩标准,MPEG音频文件是MPEG1标准中的声音 ...

  10. "git rm" 和 "rm" 的区别

    "git rm" 和 "rm" 的区别 FEB 3RD, 2013 | COMMENTS 这是一个比较肤浅的问题,但对于 git 初学者来说,还是有必要提一下的 ...