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. Oracle 10046 event详解-转载

    0046事件概述Oracle的10046事件,可以跟踪应用程序所执行的SQL语句,并且得到其解析次数.执行次数,CPU使用时间等信息.这对我们分析.定位数据库性能问题是非常有用的. 10046 eve ...

  2. TestCase--网站注册模块

    对于web测试,注册模块是必测的一个点,所以今天就来总结一下注册模块的测试用例 参考京东的注册页面 测试用例设计如下: 一.功能测试 1.  单击“免费注册”,页面是否正常跳转 2.  直接访问注册页 ...

  3. zepto的clone方法于textarea和select的bug修复

    (function($) { Zepto.fn.clone = function() { var result = $.fn.clone.apply(this, arguments), oldText ...

  4. matlab 椭圆方程拟合

    拟合椭圆首先要知道各个点的坐标,然和带入如下公式: x = [59 136 58 137 57 137 56 137 55 138 54 139 53 140 52 141 51 142 51 143 ...

  5. linux取某个字段排重

    排重统计 cat a.txt | awk -F ';' '{print $2}' | sort -u | wc -l

  6. C++临时变量的生命周期

    C++ 中的临时变量指的是那些由编译器根据需要在栈上产生的,没有名字的变量.主要的用途主要有两类: 1) 函数的返回值, 如: string proc() { return string(" ...

  7. Android基础总结(8)——服务

    服务(Service)是Android中实现程序后台运行的解决方案,它非常适合用于去执行哪些不需要和用户交互而且还要长期运行的任务.服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了 ...

  8. 华为OJ平台——24点游戏

    题目描述: 给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利 输入: 4个1-10的数字.[数字允许重复,测试用例保证无异常数字]输出: true or false 思路:

  9. LSP“浏览器劫持概念

    关于Winsock LSP“浏览器劫持”,中招者一直高居不下,由于其特殊性,直接删除而不恢复LSP的正常状态很可能会导致无法上网所以对其修复需慎重.   先说说什么是Winsock LSP“浏览器劫持 ...

  10. .NET本质论之三(应用程序对象 )

    2.1 请求的处理参数------上下文对象HttpContext   现在,请求已经到达了ASP.NET服务器,为了处理请求,ASP.NET在服务器上创建了HttpRequest类型的对象以表示请求 ...