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. Socket层实现系列 — 睡眠驱动的同步等待

    主要内容:Socket的同步等待机制,connect和accept等待的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 概述 socket上定义了 ...

  2. 四大组件之 BroadcastReceiver小结

    总结提高,与君共勉 1. BroadcastReceiver是什么? BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来接收来自系统和应用中的广播. ...

  3. 4.6、Libgdx线程介绍

    (原文:http://www.libgdx.cn/topic/48/4-6-libgdx%E7%BA%BF%E7%A8%8B%E4%BB%8B%E7%BB%8D) 所有的ApplicationList ...

  4. Linux进程-命令行参数和环境列表

    命令行参数 在C中,main函数有很多的变种,比如 main(), int main(), int main(int argc, char *argv[]), int main(int argc, c ...

  5. python的安装,IDLE基本操作

    §一.安装Python 1. 下载Active Python安装包 根据你机器型号download Python,32b选择for windows X86,64b选择for window 64b 2. ...

  6. STL - set和multiset

    set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. set采用红黑树变体的数据结构实现, ...

  7. 计算机编码方式详解(Unicode、UTF-8、UTF-16、ASCII)

    整理这篇文章的动机是两个问题: 问题一: 使用Windows记事本的"另存为",可以在GBK.Unicode.Unicode big endian和UTF-8这几种编码方式间相互转 ...

  8. [译] NSScanner:一个陌生的条件判断利器!

    NSScanner官方文档 NSScanner类是一个类簇的抽象父类,该类簇为一个从NSString对象扫描值的对象提供了程序接口. NSScanner对象把NSString 对象的的字符解释和转化成 ...

  9. ping通windows下虚拟机上的linux系统

    直接ping  linux的ip 直接就失败了. 现在我的windows有两个虚拟网卡 接下来让linux使用VMnet8网卡 修改我的linux系统下的lo网卡的ip地址为VMnet8的ip地址 现 ...

  10. iOS监听模式之KVO、KVC的高阶应用

    KVC, KVO作为一种魔法贯穿日常Cocoa开发,笔者原先是准备写一篇对其的全面总结,可网络上对其的表面介绍已经够多了,除去基本层面的使用,笔者跟大家谈下平常在网络上没有提及的KVC, KVO进阶知 ...