第十一章 管理类型(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 ...
随机推荐
- 测试一个域名DNS查询时间的shell脚本
脚本内容: #!/bin/bash #目标域名 site=${site:-www.ptesting.com} for((i=1;i<=10000;i++)) do #COUNTER='e ...
- 同步灵无线锂电鼠G11-580HX独特“五灵键”
http://tieba.baidu.com/p/2130455709 现在鼠标功能越来越强大,游戏鼠标的宏设置,办公鼠标的复制粘贴等.各位有没有给鼠标设置一些好玩.方便.搞怪.有意思的的功能的呢?笔 ...
- ORACLE 导空表结构
exp username/psd@sid file='E:\xx.dmp' tables=(xxx_%) ROWS=N 以下代码没什么用,我就乱写 set oracle_sid=ora11gsqlpl ...
- Oracle之别名小结
今天在写一个简单的SQL语句并执行时抛出了如下图所示的一个错误提示信息! 恩,此异常信息很明显,在SQL语句中标示符的长度过长了,简短一些就应该没问题了,我查看了一下我的SQL语句发现是我的查询字段的 ...
- Java中几种常见的排序方式
冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字 ...
- java 中的fanal
三.java中有final final 修饰符 关键字可用于修饰类,变量和方法,final关键字有点类似于C#里的sealed 关键字,用于表示它修饰的类,方法和变量不可改变. fina修饰变量时,表 ...
- pxecfg&kickstart生成脚本
em tm 00:00:00:00:00:12 10.180.1.12 255.255.255.0 173.45.34.25 255.255.255.225 173.45.34.1 em tm 00: ...
- 解决Linq第一次调用存储过程时速度慢的问题
最近做项目,发现linq调用存储过程,第一次时会速度慢,但之后速度都很快,过一阵子又会慢一下,以实际的操作为例子: using (FruitDbDataContext dbo = new FruitD ...
- MySQL初夜(乱码问题,命令行客户端使用)
一.乱码问题 装好MySQL,并且将数据从SQLServer导入到MySQL之后,程序一直报错. 解决方案: 首先,输入命令: show variables like "character_ ...
- C# 反射操作方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...