C#内存泄露与资源释放 经验总结
本文链接:http://blog.csdn.net/yokeqi/article/details/41083939
C#相比其他语言,拥有强大的垃圾回收机制,但并不是这样,你就可以对内存管理放任不管,其实在稍不注意的时候,可能就造成了内存泄露,甚至因此程序崩溃。
以下是遇到过的内存优化-内存泄露的问题与应对方案。
场景:
1. Form.ShowDialog()问题。
private void button1_Click(object sender, EventArgs e)
{
new Form2.ShowDialog();
}
如果你觉得写这样的一段代码很Cool,很简洁,你在项目也有这么写代码,那你就碰到大麻烦了,你试试在Form2中开个大一点的数组来检查内存,然后运行,按几下button1按钮,你就会发现,内存一直增加,即使你调用GC也无济于事。
2. 窗体向全局性事件注册了事件的问题。
public Form2()
{
InitializeComponent();
MyApp.FormChanged += FormChanged;
}
MyApp是一个静态类,如果向这种类里面注册了事件,而又没有取消注册,这样也会遇到大麻烦。即使在外部已经记得调用了Form2实例的Dispose也是没用的。
实际上由于各个开发人员的水平跟接触面不同,又没有经过统一的培训(各个人对内存释放的理解与关注度不同,或者写代码时就没考虑内存未被释放这种问题),发现问题的时候项目往往已经做到了一个阶段(SIT测试),系统也比较庞大了,这种时候才发现内存泄露的问题确实是很头疼的。
解决方案:
1. 基于架构师的经验,或者统一意见会议,在开发前对开发人员进行必要的统一培训,对关系到性能、内存等会影响系统稳定性的解决方案进行培训。这本身既有助于开发人员水平的提高,也对系统的稳定性方面提供很大的保障(项目可不是做完一个就没了,这种培训会带来长久的增益效果)。
2. 注意托管资源与非托管资源的释放区别,非托管资源是需要手动释放的。
3. 使用using关键字,避免忘记Dispose的情况,如上面的ShowDialog问题。(using中还起到了try-catch的作用,避免由于异常未调用Dispose的情况)
4. 使用UnLoad事件或者析构函数,对注册的全局事件进行取消注册。
5. 特别注意自定义组件的稳定性更重要,发生问题时影响也更广。注意继承IDisposable接口,进行资源释放,并且对有疑问/复杂逻辑的地方添加try-catch语句。(发现问题的人员不一定有权限修改这些组件)一定要保证组件健壮健壮,再健壮。这是我做组件的感悟~~~多么痛的领悟!!
最后特别奉送一个"内存释放"的大招:
调用这个API能让你的内存一下爆减:贴一段网上的示例代码
[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
/// <summary>
/// 释放内存
/// </summary>
public static void ClearMemory()
{
GC.Collect();
GC.WaitForPendingFinalizers();
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
}
}
是不是很给力,一调用内存就降下来。先别高兴太早,这其实是伪释放,只为暂时解决内存大量泄露导致系统崩溃而急需解决的情况。
具体原因:http://blog.sina.com.cn/s/blog_49f8960e0100081x.html,关键字:将物理内存转到虚拟内存,涉及磁盘读写。
好处坏处都贴出来了,是否需要使用请君自己斟酌。
---------------------
作者:笨蛋的天赋
来源:CSDN
原文:https://blog.csdn.net/yokeqi/article/details/41083939
版权声明:本文为博主原创文章,转载请附上博文链接!
C#内存泄露与资源释放 经验总结的更多相关文章
- 【转】.. Android应用内存泄露分析、改善经验总结
原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194 ...
- vld,Bounds Checker,memwatch,mtrace,valgrind,debug_new几种内存泄露检测工具的比较,Valgrind Cheatsheet
概述 内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况,在大型的.复杂的应用程序中,内存泄漏是常见的问题.当以前分配的一片内存不再需要使用或无法访问时,但是却 ...
- 关于Android 的内存泄露及分析
一. Android的内存机制Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的释 ...
- 关于Android 的内存泄露及分析(转)
一. Android的内存机制Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的释 ...
- 基于HTML5的WebGL应用内存泄露分析
上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...
- Valgrind检测内存泄露简介
原文地址: Valgrind 概述 体系结构 Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合.Valgrind由内核(core)以及基于内核的其他调试工具组成.内核 ...
- C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针
C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...
- Flex内存泄露解决方法和内存释放优化原则
Flex内存泄露解决方法和内存释放优化原则 你对Flex内存泄露的概念是否了解,这里和大家分享一下Flex内存释放优化原则和Flex内存泄露解决方法,希望本文的介绍能让你有所收获. Flex内存释放优 ...
- JNI手动释放内存(避免内存泄露)
. 哪些需要手动释放? 不要手动释放(基本类型): jint , jlong , jchar 需要手动释放(引用类型,数组家族): jstring,jobject ,jobjectArray,jint ...
随机推荐
- 模板模式创建一个poi导出功能
之前的导出都很乱,直接写在代码中,等到下回还使用导出功能时又不知如何下手,今天用模板模式重写了一个导出功能,方便以后使用: package com.sf.addrCheck.util.export.p ...
- redis集群cluster简单设置
环境: 这里参考官方使用一台服务器:Centos 7 redis-5.0.4 192.168.10.10 redis集群cluster最少要3个主节点,所以本次需要创建6个实例:3个主节点,3 ...
- 何为KVM克隆和快照
KVM的克隆.快照都是老生常谈的问题,资料也非常多,这里只是针对个人实验的记录,方便以后查阅. 虚拟机克隆 虚拟机的克隆操作是再频繁不过了,安装好第一台虚拟机后就可以进行基础设置,已此虚拟机为模板,以 ...
- 【转载】Gradle学习 第九章:Groovy快速入门
转载地址:http://ask.android-studio.org/?/article/17 To build a Groovy project, you use the Groovy plugin ...
- Activity + 基础UI
目录 Activity + 基础UI 1. 返回键退出进入应用: 2. home键以后 3. home键退出切换字体 二:AndroidManifest配置theme改变UI效果 三:UI 报错: A ...
- Python基础-numpy
创建数组 numpy.array():括号内可以是列表.元祖.数组.生成器等 numpy.arange():类似range(),在给定间隔内返回均匀间隔的值 #numpy.linspace() 返回在 ...
- 转:Oracle中SQL语句执行过程中
Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1.当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法.表名.字 ...
- Python之request模块-基础用法
Request模块参考中文手册:https://requests.readthedocs.io/zh_CN/latest/ Request模块 1.查看pip已装包(模块)的安装信息(模块的路径.版本 ...
- python之pip安装软件包常用命令
# pip版本号查询 pip -V # 安装软件包.格式:pip install 软件包名 pip install pygame # 安装指定版本号的软件包.格式:pip install 软件包==软 ...
- 使用Git Flow规范!
Git Flow常用的分支 Production 分支 也就是我们经常使用的Master分支,这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从其他分支合并,不能在这个分支直 ...