第十一章 管理类型(In .net4.5) 之 管理对象的生命周期
1. 概述
本章内容包括 管理非托管资源、使用IDisposable接口 以及 管理析构器和垃圾回收。
2. 主要内容
2.1 理解垃圾回收机制
① 代码执行的时候,内存中有两个地方存放数据项:堆 和 栈。
② 一个方法结束的时候,其使用的栈空间会被自动清空。 而堆空间,是由垃圾回收器管理的。
③ 垃圾回收器的工作原理是:启动以后,垃圾回收器的标记程序会遍历堆上保存的对象,标记出仍然被引用的对象,然后压缩程序启动,它会把当前仍然存在引用的对象移动到一起,然后释放掉其他不存在引用的对象。
④ 执行垃圾回收期间,为了确保对象状态的准确性,系统会暂停其他所有线程的执行,直到垃圾回收执行完毕。这可能会导致一定的程序响应问题。
⑤ 为了解决上述问题,垃圾回收器被设计成智能的。它会尽量在堆空间不足或内存不足的时候启动,而且尽量会在程序使用率低的时候启动。
⑥ 执行标记程序的时候,首次遍历到的对象默认是Generation 0,如果检测到该对象存在引用,则会提高该对象的Generation。其中根据的原则是:长时间停留的对象,可能会停留较长时间。所以这些对象仅会在空间不足的时候才会去检测和释放。
2.2 管理非托管资源
不涉及非托管资源的时候,基本无需考虑内存及资源管理问题,垃圾回收器都能处理好。但是一旦涉及到非托管资源,垃圾回收器就无能为力了,这时候就需要手动释放资源。
析构器(finalizer)是释放资源的一种方式,但是C#中,析构器的执行时间是不确定的,是由垃圾回收器的算法决定的。但是可以通过调用GC.Collect来强制执行析构器。(这种做法是不推荐的)
- StreamWriter sw = File.CreateFile("temp.dat");
- sw.Write("some data");
- GC.Collect();
- GC.WaitForPendingFinalizers();
- File.Delete("temp.dat");
析构器延长了对象的生命周期。因为析构器总要执行,.net平台会在一个特殊的析构队列中保存一个该对象的引用。这会推迟垃圾回收器的回收时间。
综上所述,对于释放非托管资源,析构器不是一个很好的方案。.net有更好的推荐:IDisposable。
- using(StreamWriter stream = File.CreateText(“temp.dat”))
{- stream.Write(“some data”);
- stream.Dispose();
- File.Delete(“temp.dat”);
}
使用using,可以自动处理其中代码的异常情况,避免因为代码中的异常可能导致的资源没有释放的问题。
2.3 实现IDisposable接口和析构器
在自定义类型中同时实现IDisposable接口和析构器,是一个必要的方案。可以避免用户忘记调用Dispose方法的情况。
- class UnmanagedWrapper : IDisposable
- {
- public FileStream Stream { get; private set;}
- public UnmananagedWrapper()
- {
- this.Stream = File.Open("temp.dat", FileMode.Create);
- }
- ~UnmanagedWrapper()
- {
- Dispose(false);
- }
- public void Close()
- {
- Dispose();
- }
- public void Dispose()
- {
- Dispose(true);
- System.GC.SuppressFinalizer(this);
- }
- public void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (Stream != null)
- Stream.Close();
- }
- }
- }
* System.GC.SuppressFinalizer(object obj)会请求系统不要调用指定对象的析构器。
2.4 弱引用(weak references)
- static WeakReference data;
- public static void Run()
- {
- object result = GetData();
- //GC.Collect(); 取消这行注释将会导致data.Target为null
- result = getData();
- }
- private static object GetData()
- {
- if (data == null)
- data = new WeakReference(LoadLargeList());
- if (data.Target == null)
- data.Target = LoadLargeList();
- return data.Garget;
- }
弱引用可用于缓存场景,用弱引用定义的对象,不会阻碍垃圾回收器的回收。上面的GetData方法,确保在对象被回收以后,重新获取并保存对象。
3. 总结
① C#中,用堆和栈在内存中保存数据项。堆空间是受垃圾回收器管理的。
② 垃圾回收器会释放堆上那些已经不存在引用的对象。
③ 析构器是类中一段特殊的代码,在类对象被删除的时候,由垃圾回收器负责调用。
④ IDisposable接口,可以实现用可控的方式来释放非托管资源。
⑤ 可以用using关键字来确保实现了IDisposable的对象总会被成功释放。
⑥ 弱引用 可以保存一个对象,该对象会被垃圾回收器当做已经没有引用的对象而回收。
第十一章 管理类型(In .net4.5) 之 管理对象的生命周期的更多相关文章
- 第十二章 管理类型(In .net4.5) 之 操作字符串
1. 概述 本章包括 字符串基本操作 以及 查找.遍历.格式化字符串. 2. 主要内容 2.1 在.net平台中使用字符串 C#中,string是用来保存文本信息的.是一个被当做值类型使用的引用类型. ...
- 第七章 管理类型(In .net4.5) 之 使用类型
1. 概述 本章介绍 值类型的装箱拆箱.类型转换 以及 C#4.0新推出的 dynamic 关键字. 2. 主要内容 2.1 装箱和拆箱 2.2 类型转换 有四种方式可以实现类型转换: ① 隐式转换: ...
- 第六章 管理类型(In .net4.5) 之 创建类型
1. 概述 本章内容包括 C#5中如何更好的创建类型以及如何扩展现有类型. 2. 主要内容 2.1 如何选择类型 C#类型系统包括三种类型:值类型.引用类型.指针类型.(指针类型用于非托管代码,很少使 ...
- 第九章 管理类型(In .net4.5) 之 继承机制
1. 概述 本章包括 设计和实现接口.创建和使用基类 以及 使用.net类库提供的标准接口. 2. 主要内容 2.1 设计和实现接口 一个接口包含公共的方法.属性.事件.索引器.类和结构都可以实现接口 ...
- 第二十一章 数据访问(In .net4.5) 之 序列化
1. 概述 应用程序间传递数据,需要先将数据对象转化为字符流或字节流的形式,然后接收端收到后再转化回原始的数据对象.这就是序列化与反序列化. 本章介绍 .net中的序列化与反序列化.序列化器的种类 以 ...
- 第十章 管理类型(In .net4.5) 之 使用反射
1. 概述 一个.net程序不仅包含代码和数据,还包含 元数据. 本章介绍如何应用attributes以及如何使用反射来获取它,还有如何使用CodeDom和expression trees来实现在运行 ...
- 第八章 管理类型(In .net4.5) 之 加强封装
1. 概述 本章内容包括 访问控制符.属性 和 显式接口实现. 2. 主要内容 2.1 访问控制符 封装的核心是隐藏信息.访问控制符用来实现类型成员的访问控制. C#的访问控制符有:public, i ...
- 第十一章 Function类型
在ECMAScript中,Function(函数)类型实际上是对象.每个函数也是Function类型的实例,而且都与其它引用类型一样具有属性和方法.由于是函数对象,因此函数名实际上也是一个指向函数对象 ...
- 第三章 设计程序架构 之 设计实现Windows Azure 角色生命周期
1. 概述 Windows Azure 是微软的云计算平台.用于 在微软数据中心 通过全局网络 生成.发布和管理应用程序. 本章内容包括 startup tasks 以及 实现 Start, Run ...
随机推荐
- PetaPoco.Core.ttinclude修改
/// <summary> /// Adds the singular rule. /// </summary> /// <param name="rule&q ...
- Oracle VM VirtualBox 安装笔记
[CentOS 6] 1.在官网下载VirtualBox-4.2-4.2.16_86992_el6-1.x86_64.rpm安装. 2.YUM安装kernel-devel包. 3.把用户加入vboxu ...
- <iOS>other linker flags[转]
包含静态库时候需要在Target的Other linker flags里面加上值:-objC,-all_load,-force_load 对于64位机子和iPhone OS应用 解决方法是使用-all ...
- MFC获取文本框字符串
//方法1:使用用GetDlgItem,得到控件对像, 再GetWindowText //GetDlgItem(IDC_EDIT1)->GetWindowText() //方法2:控件与对应类关 ...
- 一名合格QA的基本素养
测试不是无脑的重复劳动.测试与开发一样,先用脑,再动手. 拒绝搬砖,关注技术: 把握需求,极致体验: 把控进度,高效沟通: 测试技术 如果你只会加班,行万里路,也只是个邮差 将程序测"好 ...
- panguan(判官):一个自研的任务执行引擎的工程实践
来某厂接近半年了,几乎没写过C++代码,说实话还真的有点手生.最近刚好有一个需求,然而我感觉我也没有办法用C++以外的语言去实现它.于是还是花了几天时间用C++完成编码,这是一个简单的任务执行引擎,它 ...
- memcached学习(4). memcached的分布式算法
memcached的分布式 正如第1次中介绍的那样, memcached虽然称为"分布式"缓存服务器,但服务器端并没有"分布式"功能. 服务器端仅包括 第2次. ...
- JS判断手机浏览器
<script type="text/javascript"> /* * 智能机浏览器版本信息: * */ varbrowser={ versions:function ...
- 如何使用编辑模板在ASPxGridView中进行新增修改(除去常规的gridviw模板编辑外)
aspgridview模板编辑效果图: //前端代码:(核心: <Templates><EditForm>.....中间可用栅格样式布局等(随意)...</Templat ...
- JavaBean和内省
JavaBean和内省 JavaBean是一个遵循特定的写法的java类 1. 必须有一个无参的构造方法 2.属性私有化 3.私有你给的属性必须通过public类型的方法暴露给 ...