目的

为了及时释放宝贵的非托管资源和托管资源,并且保证资源在被 gc 回收的时候可以正确释放资源,同时兼顾执行效率。

必须遵循的事实

1 .  托管资源释放:
  由另一线程的 gc 进行释放,当托管的对象没有被引用时,就会在“适当的时候”进行回收。
  如果定义了析构函数,回收的时候会调用析构函数(实际执行可能有差别),之后释放对象占用的内存。
  当类有析构函数时, gc 会分分两步来释放,如果没有析构函数或者指定不需要调用析构函数时,只需要一步就能释放。

2.  非托管资源必须显式释放

方案

1.  把资源释放都放在析构函数里

可以保证资源都释放,但是由于 gc 调用时机的不确定性,导致宝贵的非托管资源无法及时释放。

2.  写个释放函数,手动是调用

如果忘了释放的话, 托管资源会被 gc 释放,但非托管资源就无法释放

3.  Dispose 模式。参考下面的代码

手动调用Dispose() 可以释放所有资源,并且在 gc 标记不需要再调用析构函数,从而提高了效率。如果忘记调用Dispose(), 则当 gc 调用析构函数的时候也会把非托管资源释放掉。

参考代码

public interface IDisposable
{void Dispose();
}
public class DisposablClass : IDisposable
{//是否回收完毕bool _disposed;public void Dispose(){Dispose(true);GC.SuppressFinalize(this); //标记gc不在调用析构函数}~DisposableClass(){Dispose(false);}private void Dispose(bool disposing){if(_disposed) return; //如果已经被回收,就中断执行if(disposing){//TODO:释放本对象中管理的托管资源}//TODO:释放非托管资源_disposed = true;}
}

可能存在的疑问

既然 gc 是另外一线程执行的,为什么Dispose(bool)函数里不加锁?

因为如果可以主动调用的时候,肯定此对象不是死对象,也不会被回收,因此不会同时调用到哪里不太对,但又说不上来。

为什么析构函数调用的dispose(false)不释放托管资源?

因为析构函数由 gc 来调用,gc 会依次释放所有的死对象(不可到达),释放的顺序是随机的,如果在一个对象的析构里调用了一个本次 gc已经释放的对象,就会发生释放两次的错误。

C# Dispose模式相关推荐

  1. Effective C# 原则18:实现标准的处理(Dispose)模式(译)

    Effective C# 原则18:实现标准的处理(Dispose)模式 我们已经讨论过,处理一个占用了非托管资源对象是很重要的.现在是时候来讨论如何写代码来管理这些类占用的非内存资源了.一个标准的模 ...

  2. 利用C#实现标准的 Dispose模式

    我们已经知道了处置那些占用非受控(unmanaged)资源的对象的重要性,现在应该编写资源管理代码来处置那些包含非内存资源的类型了.整个.NET框架组件都使用一个标准的模式来处理非内存资源.使用你建立 ...

  3. C#中的Dispose模式

    C#中的资源 在我们的程序中,使用资源后,需要释放.那么在C#中的每一种资源,可以分为两类: - 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: - 非托管资源:不受CLR管理 ...

  4. 行动力决定了一个人的成败,有想法,就去做! C#的内存管理原理解析+标准Dispose模式的实现

    尽管.NET运行库负责处理大部分内存管理工作,但C#程序员仍然必须理解内存管理的工作原理,了解如何高效地处理非托管的资源,才能在非常注重性能的系统中高效地处理内存. C#编程的一个优点就是程序员不必担 ...

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

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

  6. C# Dispose模式详细分析

    C#Dispose模式 目的: 为了及时释放宝贵的非托管资源和托管资源,并且保证资源在被gc回收的时候可以正确释放资源,同时兼顾执行效率 必须遵循的事实: 1 托管资源释放: 由另一线程的gc进行释放 ...

  7. Effective C# Item18:实现标准Dispose模式

    如果一个类型中包含了非托管的资源,那么我们应该自己编写释放非托管资源的方法..NET提供了一个标准的用于释放资源的模式,叫做Dispose模式,在这种模式中,类型实现IDisposable接口,并提供 ...

  8. C#实现标准的Dispose模式

    上一章说过,对于对象包含非托管资源,要正确的加以清理.对于非托管资源来说,.net framework 会采用一套标准的模式来完成清理工作,因此,如果你编写的类里面用到了非托管资源,那么该类的使用者就 ...

  9. C#Dispose模式

    C#Dispose模式 目的: 为了及时释放宝贵的非托管资源和托管资源,并且保证资源在被gc回收的时候可以正确释放资源,同时兼顾执行效率 必须遵循的事实: 1 托管资源释放: 由另一线程的gc进行释放 ...

最新文章

  1. 【组合数学】组合数学简介 ( 组合数学脉络 | 组合数学技巧 | 组合思想 1 : 一一对应 )
  2. vue工程本地代码请求http发生跨域提示错误解决方法
  3. 深度解读 MongoDB 4.4 新特性
  4. 龙芯3A5000初样顺利交付流片
  5. FRIDA - API使用篇:rpc、Process、Module、Memory 使用方法及示例
  6. 云原生数据库崛起,阿里云POLARDB当选世界互联网领先科技成果
  7. dev用不了_跟风喊AMD YES?很多生产力项目,你必须用IU
  8. 用c语言编译二叉树,C语言 数据结构平衡二叉树实例详解
  9. quot;蓝筹quot;如何使程序猿?
  10. 计算机 管理策略,有关管理组策略管理模板的建议 (.adm) 文件
  11. 在VC++ 6.0下利用共享内存、消息实现内部进程通讯
  12. Sendmail with Attachment script
  13. python源码剖析_Python源码剖析的作品目录
  14. A Game with Traps—— 二分
  15. 博士申请 | 新加坡国立大学Xinchao Wang老师招收图神经网络方向博士/博后
  16. 算法打卡Ques20201009
  17. 基于vue+spring的博客系统
  18. TCP协议全面实验分析详解
  19. Java读取hdfs文件权限问题
  20. 基于Matlab的遗传算法程序设计及优化问题求解

热门文章

  1. [javaEE] JDBC快速入门
  2. [leetcode]Pascal#39;s Triangle II
  3. C++ Exercises(十五)--排序算法的简单实现
  4. icewm使用心得[转]
  5. 请先设置tkk_理光MP2014扫描至文件夹的设置方法
  6. iec104点号_IEC104报文流程(有常用类型标识解释)
  7. python enumerate函数_关于python中enumerate和zip函数的用法及举例
  8. Chrome OS 云里雾里
  9. 关于epoll,select,poll的理解
  10. JavaScript全面学习(中阶)