C#Dispose模式

  • 目的:

    为了及时释放宝贵的非托管资源和托管资源,并且保证资源在被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;
}
}
  • 可能存在的疑问

    1. 既然gc是另外一线程执行的,为什么Dispose(bool)函数里不加锁?
     答:因为如果可以主动调用的时候,肯定此对象不是死对象,也不会被回收,因此不会同时调用到

    2. 为什么析构函数调用的dispose(false)不释放托管资源?
        答:因为析构函数由gc来调用,gc会依次释放所有的死对象(不可到达),释放的顺序是随机的,如果在一个对象的析构里调用了一个本次gc已经释放的对象,就会发生释放两次的错误。

  • 这个讲的也不错,就是有点啰嗦:

    https://blog.csdn.net/zrf2112/article/details/50644652

C# Dispose模式详细分析的更多相关文章

  1. 基于Java 生产者消费者模式(详细分析)

    Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...

  2. Java 生产者消费者模式详细分析

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. activity的四种启动模式详细分析

    1.android中通过任务队列来管理activity 采用栈的结构就是后进先出 手机里面如果启动多个应用就会启动多个任务栈来管理对应的activity. 主要解决下面的问题:对应的四种启动模式: 1 ...

  4. Android-Native-Server 启动和注册详细分析

    Android-Native-Server 启动和注册详细分析     以mediaService为实例来讲解: mediaService的启动入口 是一个 传统的  main()函数 源码位置E:\ ...

  5. Http Pipeline详细分析(下)

    Http Pipeline详细分析(下) 文章内容 接上面的章节,我们这篇要讲解的是Pipeline是执行的各种事件,我们知道,在自定义的HttpModule的Init方法里,我们可以添加自己的事件, ...

  6. /etc/rc.d/init.d/functions文件详细分析

    /etc/rc.d/init.d/functions文件详细分析 functions这个脚本是给/etc/init.d里边的文件使用的(可理解为全局文件). 提供了一些基础的功能,看看里边究竟有些什么 ...

  7. 微软和Google的盈利模式对比分析

    一: 微软和Google是世界上最成功科技巨头之一,但他们之间却有着不同的产品和业务,二者的盈利方式也各有不同,本文将分析和探讨的二者盈利模式的异同. 微软的盈利模式 在1975年由大学肄业的Bill ...

  8. IDea 工具debug模式详细使用说明

    IDea 工具debug模式详细使用说明 IDEA中如何使用debug调试项目 一步一步详细教程 Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生 ...

  9. 13万字详细分析JDK中Stream的实现原理

    前提 Stream是JDK1.8中首次引入的,距今已经过去了接近8年时间(JDK1.8正式版是2013年底发布的).Stream的引入一方面极大地简化了某些开发场景,另一方面也可能降低了编码的可读性( ...

随机推荐

  1. 【翻译】Ext JS 6有什么新东西?

    工具包ToolKits 发布 包的命名 Fashion 图表 ItemEdit插件 网格 电子表格 可操作模式Actionable Mode和可访问性 LazyItems插件 屏幕阅读器支持可访问性 ...

  2. Dynamics CRM2013 Server2012下部署ADFS和IFD遇到的问题No Organization were retrived

    最近一直在折腾Windows Server2012下的IFD部署,其中各种纠结啊错误百出,要想顺利的一步到位只能说看你的RP怎么样了,具体的操作过程推荐看下勇哥的博客:http://luoyong02 ...

  3. tomcat集群机制剖析及其生产部署选型

    为什么要使用集群? 为什么要使用集群?主要有两方面原因:一是对于一些核心系统要求长期不能中断服务,为了提供高可用性我们需要由多台机器组成的集群:另外一方面,随着访问量越来越大且业务逻辑越来越复杂,单台 ...

  4. tomcat整合apache

    历时4个多小时,终于把tomcat与apache整合起来了. 中间出了各种各样的问题,现记录一下,也希望能对后来者有点帮助. 背景 apache与tomcat的区别联系大家都知道: tomcat能处理 ...

  5. android报错 Expected BEGIN_OBJECT but was STRING at line 1 column 39 path $

    我在使用retrofit和Gson配合时,出现了这个问题,疑惑中乱七八糟瞎搞了一个下午没有解决.期间怀疑Gson解析不能使用泛型(因为我的解析使用了泛型),后来又觉得可能是我的关键字正好是解析器的某个 ...

  6. Learning ROS for Robotics Programming Second Edition学习笔记(二) indigo tools

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  7. 苹果新的编程语言 Swift 语言进阶(十六)--泛型

    泛型允许你定义一个宽松.可重用的函数或者类型,使用泛型能够避免代码的重复,也能以更清楚和抽象的方式来表达程序的意图. 泛型是Swift语言提供的强大功能之一,Swift提供的许多标准库都使用了泛型来创 ...

  8. 运行Myeclipse时,如何删除IVM窗口

    windows------>preference------>run/debug------->lauching--------->percpectives,改成never,n ...

  9. linux打包压缩常用命令

    打包: zip   gzip  bzip2 tar  xz     //rar zip 包 zip   xxx.zip     test.c  压缩 unzip  xxx.zip            ...

  10. spring注解关键字

    spring注解: (1)@Controller   控制器 (2)@Autowired    按照类型匹配,可以完成对类成员变量,方法及构造函数进行标注,完成自动装配的工作   @Autowired ...