C#中资源分为托管资源和非托管资源。 托管资源由垃圾回收器控制如何释放,不需要程序员过多的考虑(当然也程序员也可以自己释放)。 非托管资源需要自己编写代码来释放。那么编写好的释放非托管资源的代码(释非代码)由谁来调用呢。有两种实现方式:

一 将释非代码放到构造函数析构函数中,由系统自动调用,系统会在资源对象不再使用了,会在某个时间调用构造函数析构函数来释放非托管资源。构造函数析构函数的目的就是用来释放或清理非托管资源的。但它有一个问题是调用的时间是系统说了算,不能在程序中自己想要调用时调用析构函数,这是C#规定的。那么就产生了第二种方式。

二 将释非代码放到另外一个函数中,当自己想调用时就调用。将释非代码放在一个方法中共用,代码如下:

 MyClass
{
~MyClass()
{
DisposePro();
} public void Dispose()
{
DisposePro();
} private void DisposePro()
{
// 释非代码
......
}
}

但是这样可能会产生其他问题。资源可能会被多次释放,而产生问题。系统会自动调用析构函数,自己也可能多次调用Dispose()方法。那么解决方法是使用一个全局变量作为标记,来标记资源是否已经被释放,已经释放就不再释放。代码如下:

   MyClass
{
private bool disposed = false;
~MyClass()
{
DisposePro();
} public void Dispose()
{
DisposePro();
} private void DisposePro()
{
if(disposed == false)
{
// 释非代码
......
}
disposed = true;
}
}

这样看起来似乎没有问题了。但是当调用Dispose()方法只能立即释放非托管资源,而托管资源还是需要由GC自动处理。那么为了能够做到调用Dispose()方法时也能够释放立即释放托管资源,则需要在DisposePro()方法中添加上想要释放的托管资源的释放代码(释放托管代码)。代码如下:

     MyClass
{
private bool disposed = false;
~MyClass()
{
DisposePro();
} public void Dispose()
{
DisposePro();
} private void DisposePro()
{
if(disposed == false)
{
// 释托管代码
......
// 释非代码
......
}
disposed = true;
}
}

这样还是有问题,当析构函数调用DisposePro()时,会调用释托管代码,可能产生问题——托管对象可能已经被GC删除了而产生问题。那么使用一个标记给DisposePro(),当是被析构函数调用时不执行释托管代码。重新命名DisposePro(),代码如下:

       MyClass
{
private bool disposed = false;
~MyClass()
{
Dispose(false);
} public void Dispose()
{
Dispose(true);
} private void Dispose(bool disposing)
{
if(disposed == false)
{
if(disposing == true)
{
// 释托管代码
......
}
// 释非代码
......
}
disposed = true;
}
}

用这段代码来释放资源应该没有问题了。看一下标准清理模式,代码如下:

     MyClass:IDisposable
{
private bool disposed = false;
~MyClass()
{
Dispose(false);
} public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} private void Dispose(bool disposing)
{
if(disposed == false)
{
if(disposing == true)
{
// 释托管代码
......
}
// 释非代码
......
}
disposed = true;
}
}

标准清理模式中多了一句GC.SuppressFinalize(this);【该方法通知CLR不要调用该方法的析构函数,因为它已经被清理了。】如果没有这句代码,我认为不影响程序的正确性,不会发生安全问题,他只是告诉系统不要再调用构造函数了。那么为什么要加上这句代码呢?如果在调用了Dispose()之后再调用析构函数只是多此一举,所以告诉系统不要再调用了。这一点应该和性能有关系。【如果不需要构造函数就不要执行构造函数,他们会带来性能上的开销】。

参考:

C#4.0 图解教程 Daniel M. Solis

相关链接:

1. 实现 Finalize 和 Dispose 以清理非托管资源 http://msdn.microsoft.com/zh-cn/library/b1yfkh5e(v=vs.90).aspx

2. GC.SuppressFinalize 方法 http://msdn.microsoft.com/zh-cn/library/system.gc.suppressfinalize(v=vs.90).aspx

C# 释放非托管资源的更多相关文章

  1. 6.C# 释放非托管资源2

    C# 释放非托管资源 C#中资源分为托管资源和非托管资源. 托管资源由垃圾回收器控制如何释放,不需要程序员过多的考虑(当然也程序员也可以自己释放). 非托管资源需要自己编写代码来释放.那么编写好的释放 ...

  2. 5.C#释放非托管资源1

    释放非托管资源 在介绍释放非托管资源的时候,我觉得有必要先来认识一下啥叫非托管资源,既然有非托管资源,肯定有托管资源. 托管资源指的是.net可以自棕进行回收的资源,主要是指托管堆上分配的内存资源.托 ...

  3. C#编程(七十四)----------释放非托管资源

    释放非托管资源 在介绍释放非托管资源的时候,我觉得有必要先来认识一下啥叫非托管资源,既然有非托管资源,肯定有托管资源. 托管资源指的是.net可以自棕进行回收的资源,主要是指托管堆上分配的内存资源.托 ...

  4. Dispose模式释放非托管资源

    实现方式用的是设计模式里的模板模式,基类先搭好框架,子类重写void Dispose(bool disposing) 即可. 需要注意的是基类的Finalize函数也就是析构函数调用的是虚函数void ...

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

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

  6. IDisposable?释放非托管资源接口

    原文:https://www.cnblogs.com/luminji/archive/2011/03/29/1997812.html IDisposable高级篇:https://docs.micro ...

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

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

  8. C# 托管非托管资源释放

    1.C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源. 2.C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析 ...

  9. .NET 清理非托管资源

    Dispose 类型的 Dispose 方法应释放它拥有的所有资源.它还应该通过调用其父类型的 Dispose 方法释放其基类型拥有的所有资源.该父类型的 Dispose 方法应该释放它拥有的所有资源 ...

随机推荐

  1. 使用Maven创建一个Spring MVC Web 项目

    使用Maven创建java web 项目(Spring MVC)用到如下工具: 1.Maven 3.2 2.IntelliJ IDEA 13 3.JDK 1.7 4.Spring 4.1.1 rele ...

  2. 课程设计之(struts2+Hibernate)航空订票系统

    1.题目 课程设计之航空订票系统 为某家机票预订服务商开发一个机票预订和查询管理系统.该系统中的航班和机票信息由多家航空公司负责提供.客户通过上网方式查询航班时间表.机票可用信息.机票折扣信息,可以远 ...

  3. Hibernate开发之二 映射主键-

    <class name="cn.itcast.e_hbm_id.User" table="user">            <!-- 映射主 ...

  4. 在Windows 上的 Python

    在 Windows 上, 安装 Python 有两种选择. ActiveState 制作了一个 Windows 上的 Python 安装程序称为 ActivePython, 它包含了一个完整的 Pyt ...

  5. android的helloworld工程目录学习

    android的helloworld工程目录学习 Android工程的主要目录有src.gen.Android X.X.bin.res等文件夹. 1.     Src文件夹 Src文件夹包含java源 ...

  6. Lists of network protocols

    https://en.wikipedia.org/wiki/Lists_of_network_protocols Protocol stack: List of network protocol st ...

  7. Git for windows 中文乱码解决方案

    1.git status时显示乱码,如下: \316\304\261\276\316\304\265\265.txt 解决方案: $ git config --global core.quotepat ...

  8. 函数xdes_init

    /**********************************************************************//** Inits an extent descript ...

  9. 函数fsp_alloc_from_free_frag

    /**********************************************************************//** Allocates a single free ...

  10. AWS 之 S3篇<.NET(c#)批量上传文件>

    第一次知道AWS然后网上就研究了一番,如果也是第一次知道这个的话,或者对这个只知道是干什么,并没有写个相关的程序的话,可以看看这个网址http://docs.aws.amazon.com/zh_cn/ ...