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. 11、Libgdx的音频

    (官网:www.libgdx.cn) Libgdx提供了简单的方法对较小的音效和磁盘中的音乐进行回放.它同样也提供了方便的针对音频硬件的读写权限. 所有的音频操作都通过audio模块来完成: Audi ...

  2. leetcode之 Palindrome Partitioning I&II

    1 Palindrome Partitioning 问题来源:Palindrome Partitioning 该问题简单来说就是给定一个字符串,将字符串分成多个部分,满足每一部分都是回文串,请输出所有 ...

  3. Linux IPC实践(11) --System V信号量(1)

    信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...

  4. Android万能适配器Adapter-android学习之旅(74)

    万能适配器的代码的github地址是https://github.com/fengsehng/CommonAdapter 万能适配器的代码的github地址是https://github.com/fe ...

  5. Java对象引用处理机制

    翻译人员: 铁锚 翻译时间: 2013年11月13日 原文链接: How does Java handle aliasing? 什么是Java的引用别名机制 Java的引用别名机制(原文为Aliasi ...

  6. 敏捷测试(7)--基于story的敏捷基础知识

    基于story的敏捷基础知识----迭代启动会.迭代回顾会 除需求讲解意外,需要所有团队成员参加的会议仅有两个,分别是"迭代启动会"和"迭代回顾会". (1)迭 ...

  7. Python学习笔记 - 字符串和编码

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- #第一行注释是为了告诉Linux/OS X系统, #这是一个Python可执行程序,Windows系统会忽 ...

  8. Java集合之Collection

    Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等.Java集合工具包位置是java.util.* Java集合主要可以划分为4个部分:List列表.Set集 ...

  9. OC语言(一)

    一.概述 1.基本上所有关键词@开头 2.字符串以@开头,如@"Hello" 3.基本数据类型 char int float double BOOL(YES\NO) 4.空为nil ...

  10. hive:(group by, having;order by)的使用;group by+多个字段,以及wiki说的group by两种使用限制验证

    hive> select * from app_data_stats_historical where os='1' group by dt limit 100; 出现结果如下: 2014-01 ...