原文

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

托管资源指的是.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;
}
}

  转自

 
 

转/ C# 托管资源和非托管资源的更多相关文章

  1. C# 托管资源与非托管资源

    在.net 编程环境中,系统的资源分为托管资源和非托管资源. 托管资源: Net平台中,CLR为程序员提供了一种很好的内存管理机制,使得程序员在编写代码时不要显式的去释放自己使用的内存资源(这些在先前 ...

  2. C# using 三种使用方式 C#中托管与非托管 C#托管资源和非托管资源区别

    1.using指令.using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到. ...

  3. C# 托管资源和非托管资源

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

  4. .net 资源释放(托管资源和非托管资源)

    1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...

  5. C# 托管资源 与 非托管资源

    C# 托管资源 与 非托管资源 托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,.NET可以自动进行回收,主要是指托管堆上分配的内存资源.例如程序中分配的对象,作用域内的变量 ...

  6. .net托管资源与非托管资源

    在项目当中用到的资源分为托管资源和非托管资源,托管资源无非就是什么int.string.datatime之类,托管资源不需要人为去管理,.net framework中有专门针对托管资源的管理机制(GC ...

  7. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

  8. [转]在C#中使用托管资源和非托管资源的区别,以及怎样手动释放非托管资源:

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

  9. C#内存管理之托管堆与非托管堆( reprint )

    在 .NET Framework 中,内存中的资源(即所有二进制信息的集合)分为“托管资源”和“非托管资源”.托管资源必须接受 .NET Framework 的 CLR (通用语言运行时)的管理(诸如 ...

随机推荐

  1. BZOJ 1108: [POI2007]天然气管道Gaz 性质分析_小结论_巧妙

    Description Mary试图控制成都的天然气市场.专家已经标示出了最好的天然气井和中转站在成都的地图.现在需要将中转 站和天然气井连接起来.每个中转站必须被连接到正好一个钻油井,反之亦然. M ...

  2. 【转载】JavaWeb之DBUtils QueryRunner类对数据表的增、删、查(8种结果集处理方式)、改操作

    一.使用QueryRunner类,实现对数据表的 insert delete update package com.shuhuadream.queryrunner; import java.sql.C ...

  3. 【转载】MySQL之CONCAT()的用法

    mysql CONCAT()函数用于将多个字符串连接成一个字符串,是最重要的mysql函数之一,下面就将为您详细介绍mysql CONCAT()函数,供您参考 mysql CONCAT(str1,st ...

  4. eas更改用户组织范围和业务组织范围

    表: T_PM_OrgRangeIncludeSubOrg 10 20 30 分别代表 业务组织 行政组织 以及管辖组织.查行政组织,

  5. 01-Linux命令基础-第01天(命令基础,软件安装与卸载、磁盘管理)

    01-   Linux初步 最早一直是单道程序设计模型的操作系统 69年贝尔实验室决定开发多道程序设计模型的操作系统 Multics计划 (失败了) x86 IA(Intel Architecture ...

  6. swift-计算字符串长度

    text.characters.count(记得text一定要是String类型)

  7. 1016 部分A+B (15 分)

    正整数 AAA 的“DAD_AD​A​​(为 1 位整数)部分”定义为由 AAA 中所有 DAD_AD​A​​ 组成的新整数 PAP_AP​A​​.例如:给定 A=3862767A = 3862767 ...

  8. 字符串函数(day11)

    使用存储区的地址作为返回值可以让调用 函数使用被调用函数的存储区 这种时候被调用函数需要提供一个指针类型 的存储区记录作为返回值的地址数据 不可以把非静态局部变量的地址作为返回值 使用 C语言里的文字 ...

  9. HDU 5729 Rigid Frameworks (联通块计数问题)

    题目传送门 通过看题解画图可以发现: 不论怎么转,一列里的横边/一行里的竖边始终平行 当我们加固一个格子时,会让它所在的这一行的竖边和这一列的横边保证垂直 而我们的目标是求所有竖边和横边都保证垂直的方 ...

  10. 数位dp题集

    题集见大佬博客 不要62 入门题,检验刚才自己有没有看懂 注意一些细节. 的确挺套路的 #include<bits/stdc++.h> #define REP(i, a, b) for(r ...