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) 之 管理对象的生命周期的更多相关文章

  1. 第十二章 管理类型(In .net4.5) 之 操作字符串

    1. 概述 本章包括 字符串基本操作 以及 查找.遍历.格式化字符串. 2. 主要内容 2.1 在.net平台中使用字符串 C#中,string是用来保存文本信息的.是一个被当做值类型使用的引用类型. ...

  2. 第七章 管理类型(In .net4.5) 之 使用类型

    1. 概述 本章介绍 值类型的装箱拆箱.类型转换 以及 C#4.0新推出的 dynamic 关键字. 2. 主要内容 2.1 装箱和拆箱 2.2 类型转换 有四种方式可以实现类型转换: ① 隐式转换: ...

  3. 第六章 管理类型(In .net4.5) 之 创建类型

    1. 概述 本章内容包括 C#5中如何更好的创建类型以及如何扩展现有类型. 2. 主要内容 2.1 如何选择类型 C#类型系统包括三种类型:值类型.引用类型.指针类型.(指针类型用于非托管代码,很少使 ...

  4. 第九章 管理类型(In .net4.5) 之 继承机制

    1. 概述 本章包括 设计和实现接口.创建和使用基类 以及 使用.net类库提供的标准接口. 2. 主要内容 2.1 设计和实现接口 一个接口包含公共的方法.属性.事件.索引器.类和结构都可以实现接口 ...

  5. 第二十一章 数据访问(In .net4.5) 之 序列化

    1. 概述 应用程序间传递数据,需要先将数据对象转化为字符流或字节流的形式,然后接收端收到后再转化回原始的数据对象.这就是序列化与反序列化. 本章介绍 .net中的序列化与反序列化.序列化器的种类 以 ...

  6. 第十章 管理类型(In .net4.5) 之 使用反射

    1. 概述 一个.net程序不仅包含代码和数据,还包含 元数据. 本章介绍如何应用attributes以及如何使用反射来获取它,还有如何使用CodeDom和expression trees来实现在运行 ...

  7. 第八章 管理类型(In .net4.5) 之 加强封装

    1. 概述 本章内容包括 访问控制符.属性 和 显式接口实现. 2. 主要内容 2.1 访问控制符 封装的核心是隐藏信息.访问控制符用来实现类型成员的访问控制. C#的访问控制符有:public, i ...

  8. 第十一章 Function类型

    在ECMAScript中,Function(函数)类型实际上是对象.每个函数也是Function类型的实例,而且都与其它引用类型一样具有属性和方法.由于是函数对象,因此函数名实际上也是一个指向函数对象 ...

  9. 第三章 设计程序架构 之 设计实现Windows Azure 角色生命周期

    1. 概述 Windows Azure 是微软的云计算平台.用于 在微软数据中心 通过全局网络 生成.发布和管理应用程序. 本章内容包括 startup tasks 以及  实现 Start, Run ...

随机推荐

  1. android View 自动 GONE 问题

    首先说一下 view visibility VISIBLE.INVISIBLE.GONE的区别: 可见(visible) XML文件:android:visibility="visible& ...

  2. Flex 仿Winxp左侧菜单

    呆毛放出,源码暂时不能公布,一直比较喜欢winxp的左侧菜单样式,以前也用xslt实现过,但总是达不到完美,没想到FLex轻松做到了这一点,几乎和winxp一模一样.

  3. Botposter.com集群ETCD2.3.7升级至3.0实录[原创]

    7月1日,为庆祝我党生日,ETCD隆重发布了3.0版本.Botposter.com也在第一时间对集群进行了升级.本文是升级过程的记录与总结(文中假设读者已经使用或测试过ETCD V2,如有不妥请见谅) ...

  4. java.lang.Exception: Socket bind failed: [730013] An attempt was made to acc

    在CMD命令行中启动运行startup.bat,启运程序总是闪退,查看日志发现如下错误: 26-Jan-2016 18:12:34.463 SEVERE [main] org.apache.coyot ...

  5. Cnetos7下,已经能访问tomcat

    进入/usr/local/apache-tomcat-8.0.24/bin 中 执行:./startup.sh开启tomcat 再执行如下 systemctl stop firewalld.servi ...

  6. .net Url重写

    详细说明及下载dll源码路径: http://msdn.microsoft.com/zh-cn/library/ms972974.aspx 顺带上本人写的一个小例子:http://files.cnbl ...

  7. EXE中释放文件

    今天有个朋友问到VC能否释放多个EXE.DLL或WAV等文件,我便做了个实例给他. (注意:以下释放资源代码是不受文件扩展名所限制的,你可以释放更多类型文件) 下面是我写了个很方面的函数给大家用! 1 ...

  8. hql 关联查询

    HQL 带的连接语句只能是实体与 该实体的属性 进行连接 其意义就是为了优化(通过延迟加载查询关联的属性)需要进行配置 from A left join A.B where (b.flag is nu ...

  9. yiStack平台维护

    <一.> yiStack 二次封装 Iso通用发行版相关配置属性值替换1.1.yiStack AIO一体机环境根据部署子网替换修改示例如下:主要修改替换isolinux/ks-aio.cf ...

  10. javascript 同步加载与异步加载

    HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值. defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面 ...