托管与非托管资源介绍及 资源的释放

托管资源与非委托资源。
托管资源:一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,例如程序中分配(new)的对象,作用域

内的变量等。
非托管资源:是CLR不能控制或者管理的部分,这些资源有很多,比如文件流,数据库的连接,系统的窗口句柄

(Window内核对象(句柄))、字体、刷子、dc打印机资源等等……这些资源一般情况下不存在于Heap(内存中用于存

储对象实例的地方)中。

-------------------------------------------------------------
C#的垃圾回收器:
    CLR为程序员提供的内存管理机制,使得程序员在编写代码时不需要显式的去释放自己使用的内存资源(这些在先

前C和C++中是需要程序员自己去显式的释放的)。这种管理机制称为GC(garbage collection)。GC的作用是很明显的

,当系统内存资源匮乏时,它就会被激发,然后自动的去释放那些没有被使用的托管资源(也就是程序员没有显式释

放的对象)。对于那些非托管资源虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理

这些资源。还好.net提供了Finalize()方法,它允许在垃圾回收器回收该类资源时,适当的清理非托管资源。但是

Finalize()会产生很多副作用。

-------------------------------------------------------------
资源的释放

Object.Cancel  方法   
 说明:取消执行挂起的异步Execute或 Open方法的调用。  
Object.Close   方法      
说明:关闭对象

Object.Dispose 方法  
说明:释放非托管资源
      资源的释放一般是通过"垃圾回收器"自动完成的,但具体来说,仍有些需要注意的地方:
  1、值类型和引用类型的引用其实是不需要什么"垃圾回收器"来释放内存的,因为当它们出了作用域后会自动释放

所占内存,因为它们都保存在栈(Stack)中;
  2、只有引用类型的引用所指向的对象实例才保存在堆(Heap)中,而堆因为是一个自由存储空间,所以它并没有像"

栈"那样有生存期("栈"的元素弹出后就代表生存期结束,也就代表释放了内存),并且要注意的是,"垃圾回收器"只对这

块区域起作用。
    然而,有些情况下,当需要释放非托管资源时,就必须通过写代码的方式来解决。

-------------------------------------------------------------
非托管资源的释放
    当我们在类中封装了对非托管资源的操作时,我们就需要显式释放(Dispose),或隐式释放(Finalize)的释放这些

资源。
Finalize一般情况下用于基类不带close方法或者不带Dispose显式方法的类,也就是说,在Finalize过程中我们需要

隐式的去实现非托管资源的释放,然后系统会在Finalize过程完成后,自己的去释放托管资源。如果要实现Dispose方

法,可以通过实现IDisposable接口,这样用户在使用这个类的同时就可以显示的执行Dispose方法,释放资源。

1.Finalizer:
   从.net2.0开始,C#编译器不能对Finalize进行显示的调用和重写,必须使用析构函数来实现它.
class A
{
~A()
{
释放资源;
}
}
    上面的代码就是通过Finalize方式来释放资源的跟C++用析构函数(终结器)释放资源的代码很象.但是它实现方式

和C++不同,因为它是由垃圾回收器来管理内存的.
  用Finalize方式释放非托管资源很简单,如果了解Finalize的实现方式,就不会选择用它来释放非托管资源.
----当GC(垃圾回收器)开始工作的时候,它首先将没有终结器的垃圾对象从内存中移除,有终结器的所有对象则添加

到一个终止化队列当中。GC会调用一个 新线程来执行这些对象的终结器。当终结器执行完毕后,这些对象会从队列中

被移除。这时候由于这些对象在第一次检测到的时候没有被释放,它们将会进入第1代 对象,直到GC检测到第0代对象

和第1代对象再次充满时,这时候GC才会把刚才那些对象释放掉,所以有终结器的对象会比没有的在内存中保留更长的

时间。
  提示:垃圾回收器把托管堆中的对象分为3代,分别是0,1,2.一般分配为:0代约256K,1代约是2MB,第2代约是

MB,代龄越高,容量就越 大,显然效率也就越低.首先被添加到托管堆中的对象被定为第0代,当第0代充满时,就会

执行垃圾回收,未被回收的对象代领将提升1代.
****由于以上原因应该避免仅使用Finalize方式释放非托管资源.

下面的规则概括了 Finalize 方法的使用指南。
1.仅在要求终结的对象上实现 Finalize。存在与 Finalize 方法相关的性能开销。
如果需要 Finalize 方法,应考虑实现 IDisposable,以使类的用户可以避免调用 Finalize 方法带来的开销。

(juky_huang注:在实现IDisposable的类中,可以通过GC.SuppressFinalize来停止Finalize的运行,这样只要显式的

调用了Dispose方法,就能给用户提供更小的开销。如果用户没有显式的调用Dispose方法,也就是没有停止Finalize

的运行,这样就可以隐式的实现非托管资源的释放)
2.不要使 Finalize 方法更可见。它应该是 protected,而不是 public。 (juky_huang注:这个很重要,Finalize方

法一般是系统调用,用户不去显式的调用它)
3.对象的 Finalize 方法应该释放对象拥有的任何外部资源。此外,Finalize 方法应该仅释放由对象控制的资源。

Finalize 方法不应该引用任何其他对象。
4.不要对不是对象的基类的对象直接调用 Finalize 方法。在 C# 编程语言中,这不是有效的操作。
5.从对象的 Finalize 方法调用 base.Finalize 方法。(juky_huang注:就是派生类调用基类的Finalize方法)
注意   基类的 Finalize 方法由 C# 和 C++ 的托管扩展的析构函数语法自动调用。

2.Dispose Pattern:
     通过IDisposable接口实现Dispose方法,这样用户在使用这个类的同时就可以显示的执行Dispose方法,释放资

源。C#提供using关键字支持Dispose Pattern进行资源释放。这样能通过确定的方式释放非托管资源,而且using结构

提供了异常安全性。所以,一般建议采用Dispose Pattern,并在Finalizer中辅以检查,如果忘记显式Dispose对象则

在Finalizer中释放资源

下面的规则概括了 Dispose 方法的使用指南:

1.在封装明确需要释放的资源的类型上实现处置设计方案。用户可以通过调用公共 Dispose 方法释放外部资源。
2.在通常包含控制资源的派生类型的基类型上实现处置设计方案,即使基类型并不需要。如果基类型有 close 方法,

这通常指示需要实现 Dispose。在这类情况下,不要在基类型上实现 Finalize 方法。应该在任何引入需要清理的资

源的派生类型中实现 Finalize。
3.使用类型的 Dispose 方法释放类型所拥有的任何可处置资源。
4.对实例调用了 Dispose 后,禁止 Finalize 方法通过调用 GC.SuppressFinalize 方法运行。此规则的例外情况是

当必须用 Finalize 完成 Dispose 没有覆盖的工作时,但这种情况很少见。
5.如果基类实现 IDisposable,则调用基类的 Dispose 方法。
6.不要假定 Dispose 将被调用。如果 Dispose 未被调用,也应该使用 Finalize 方法释放类型所拥有的非托管资源


7.处置了资源之后,在该类型(非 Dispose)上从实例方法引发一个 ObjectDisposedException。该规则不适用于

Dispose 方法,因为在不引发异常的情况下,该方法应该可以被多次调用。
8.通过基类型的层次结构将调用传播到 Dispose。Dispose 方法应释放此对象控制的所有资源和此对象所拥有的任何

对象。例如,可以创建一个类似 TextReader 的对象来控制 Stream 和 Encoding,两者均在用户不知道的情况下由

TextReader 创建。另外,Stream 和 Encoding 都可以获取外部资源。当对 TextReader 调用Dispose 方法时,它应

该依次对 Stream 和 Encoding 调用 Dispose,使它们释放它们的外部资源。
9.应考虑在调用了对象的 Dispose 方法后不允许使用对象。重新创建已处置的对象是难以实现的方案。
10.允许 Dispose 方法被调用多次而不引发异常。此方法在首次调用后应该什么也不做。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值