原文

对于这两个一直就是模模糊糊的,半知零解

托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,由.NET运行库在合适时调用垃圾回收器进行回收。

非托管资源指的是.NET不知道如何回收的资源,最常见的一类非托管资源是包装操作系统资源的对象,例如文件,窗口,网络连接,数据库连接,画刷,图标等。这类资源,垃圾回收器在清理的时候会调用Object.Finalize()(完成的意思)方法。默认情况下,方法是空的,对于非托管对象,需要在此方法中编写回收非托管资源的代码,以便垃圾回收器正确回收资源。

(就是.Net可以自己进行回收的资源是托管资源,自己不知道回收回收的就是非托管。)

注:

什么是托管资源和非托管资源?

托管资源就是托管给CLR的资源,CLR能对这些资源进行管理。

而非托管资源则是CLR无法对这些资源管理,这些资源的申请、释放必须由使用者自行管理。

例如,像Win32编程中的文件句柄,上下文句柄、窗口或网络连接等资源都属于非托管资源。但是如果这些非托管资源在.Net中进行了封装,成为了.Net类库中的一部分,它就不属于非托管资源了,因为在对它们封装的过程中,就实现了它们的自动管理功能。

也就是说,你能在.Net中找到的类产生的对象,都是托管资源。

如果按照上面做法,非托管资源也能够由垃圾回收器进行回收,但是非托管资源一般是有限的,比较宝贵的,而垃圾回收器是由CRL自动调用的,这样就无法保证及时的释放掉非托管资源,因此定义了一个Dispose()方法,让使用者能够手动的释放非托管资源。Dispose()方法释放类的托管资源和非托管资源,使用者手动调用此方法后,垃圾回收器不会对此类实例再次进行回收。Dispose()方法是由使用者调用的,在调用时,类的托管资源和非托管资源肯定都未被回收,所以可以同时回收两种资源。 Microsoft为非托管资源的回收专门定义了一个接口:IDisposable,接口中只包含一个Dispose()方法。任何包含非托管资源的类,都应该继承此接口。

原文

首先,对于垃圾回收而言,在C#中,托管资源的垃圾回收是通过CLR的Garbage Collection来实现的,Garbage Collection会调用堆栈上对象的析构函数完成对象的释放工作;而对于一些非托管资源,比如数据库链接对象等,需要实现IDisposable接口进行手动的垃圾回收。那么什么时候使用Idisposable接口,以及如何使用呢?

public interface IDisposable
{
  void Dispose();
}
public class DisposablClass : IDisposable
{
  //是否回收完毕
  bool _disposed;
  public void Dispose()//重写上面接口中的方法
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
  ~DisposableClass()
  {
    Dispose(false);
  }   
  //这里的参数表示示是否需要释放那些实现IDisposable接口的托管对象
  protected virtual void Dispose(bool disposing)
  {
    if(_disposed) return; //如果已经被回收,就中断执行
    if(disposing)
    {
      //TODO:释放那些实现IDisposable接口的托管对象
    }
    //TODO:释放非托管资源,设置对象为null
    _disposed = true;
  }
}

  

Dispose()方法

当需要回收非托管资源的DisposableClass类,就调用Dispoase()方法。而这个方法不会被CLR自动调用,需要手动调用。

总结:当我们自定义的类及其业务逻辑中引用某些托管和非托管资源,就需要实现IDisposable接口,实现对这些资源对象的垃圾回收。

我们需要编写一种方法去释放!

为了去清除一些非托管资源,你创建的类需要有一个public方法,方法的名字可以随意命名

例如:

public void Cleanup()
public void Shutdown()
你可以这么做,但是有一个标准的名字

public void Dispose()

甚至有一个接口IDisposeable,里面包含的就是刚才那个方法:

public interface IDisposable
{
 void Dispose()
}
 
因此最好的办法是让你的类去实现IDisposable接口,在接口内的Dispose方法内提供一段清除非托管资源的代码
 
public void Dispose()
{
 //这里释放一个句柄(句柄是一个非托管资源,属于Win32编程的概念)
 Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}
 
OK。这就完成了,除非你想做的更好!

别忘了类中的托管资源还占着空间!

托管资源占着空间?你首先想到的可能是那些int,string等等这些托管资源,它们能占用几个空间,他们占着就占着呗!

但是托管资源可不仅仅是那些资源,要是你的对象使用了250MB的System.Drawing,Bitmap(这是在.Net Frame中的,属于托管资源)作为一些缓冲怎么办?当然,你知道这是一个.Net的托管资源,所以GC理所应当的将会释放它。但是你真的想留着250MB的内存空间就那么被占用着?然后等待着GC最终释放它?更或者要是有一个更大数据库连接呢?我们当然不想让那连接白白占用来等待GC的终结!

如果用户调用了Dispose方法(意味着他们不再想使用这个对象里的一切)

为什么不去扔掉那些浪费空间的位图资源和数据库连接呢?

那么,我们就应该这么做:

  • 释放非托管资源(因为我们必须这么做)
  • 释放托管资源(让你的Dispose更完美)

所以,让我们更新我们的Dispose方法来释放那些托管资源

public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //Free managed resources too
if (this.databaseConnection !=null)
{
this.databaseConnection.Dispose();
this.databaseConnection =null;
}
if (this.frameBufferImage !=null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}

  转自

 
 

最新文章

  1. HTML5中createPattern()
  2. jQuery里ajax的用法
  3. HTable和HTablePool使用注意事项
  4. 使用windows远程桌面连接Windows Azure中的Ubuntu虚拟机
  5. 【转】Android Interface的使用
  6. 高难度(1)什么是AR
  7. e.target与事件委托简例
  8. Automator 简单使用流程
  9. android中sharedPreferences的笔记
  10. JDK5-可变参数
  11. shell编程/字库裁剪(2)——编程过程
  12. [bzoj4405][wc2016]挑战NPC
  13. LOJ#2668 书法家
  14. Git 与 GitHub 简介
  15. bootstrap treeview实现菜单树
  16. Delphi XE5 Android 调用手机震动
  17. Python实例获取mp3文件的tag信息
  18. Esper学习之七:EPL语法(三)
  19. UVALive 5840 数学题
  20. systemd开机启动

热门文章

  1. InnoDB undo log物理结构的初始化
  2. ffmpeg中关于EAGAIN的理解及非阻塞IO
  3. 死磕itchat源码--config.py
  4. PAT_A1134#Vertex Cover
  5. Codeforces Round #548 (Div. 2) B. Chocolates
  6. SQL第三节课
  7. grunt入门 出处:http://artwl.cnblogs.com
  8. 淘宝的开源分布式文件系统TFS
  9. 嵌入式linux实现NAT端口映射
  10. 框架统一出参数DTO格式