第七节:使用实现了dispose模式的类型

知道类型如何实现dispose模式之后,接下来看一下开发人员怎样使用提供了dispose模式的类型。这里不再讨论前面的SafeHandle类,而是讨论更常用的FileStream类。

可以利用FileStream打开一个文件,从文件中读取字节,向文件中写入字节,并关闭文件。一个FileStream对象在构造时,它会调用Win32 CreateFile函数,函数返回的句柄保存在SafeFileHandle中,然后通过FileStream对象的一个私有字段来维护运载该对象的引用,FileStream还提供了额外的几个属性(例如:Length,Position,CanRead等)和方法(例如:Read,Write,Flush等)。

假设要写代码来创建一个临时文件,并向其中写入一些字节,然后再删除该文件。开始可能会像下面这样写代码:

遗憾的是生成并运行上面的代码,它也许能工作,但是大多数情况下是不能的,问题是File的Delete方法要求Window删除一个仍然打开的文件。所以Delete方法抛出一个IOException异常.

但在某些情况下,文件可能“误打误撞”地被删除!如果另外一个线程不知怎么造成一次垃圾回收,而且这次垃圾回收刚好在调用Write之后、调用Delete之前发生,那么FileStream的SafeFileHandle字段的Finalize方法就会被调用,这回关闭文件,随后Delete操作也能正常运行。发生这种情况的概率非常小,上面代码无法运行的可能性在99%以上。

幸好FileStream实现了Dispose模式,所以可以修改代码来显示额关闭文件。下面是修改之后的源代码:

static void Main(string[] args)

{

Byte[] byteWrite = new Byte[] { 1, 2, 3, 4, 5 };

FileStream fs = new FileStream("Temp.dat", FileMode.Create);

fs.Write(byteWrite, 0, byteWrite.Length);

fs.Dispose();

File.Delete(@"d:\用户目录\我的文档\visual studio 2010\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\Temp.dat");

}

上面代码唯一的区别是添加了FileStream的dispose方法的调用。Dispose方法的调用接受一个boolen参数的dispose方法,后者在safehandle对象上调用dispose方法,该方法调用win 32的closeHandle函数,造成Windows关闭文件,然后调用File的Delete方法时,Window发现该文件已经关闭,所以成功的删除它。由于FileStream还提供了一个Close方法,所提也可以用Close方法关闭。

注意:Close方法不是dispose类正式的一部分,有的提供了Close方法,有的没有。

需要注意的是,调用Dispose或Close只是为了能在一个确定的事件强迫对象执行清理;这两个方法并不能控制托管堆中的对象所占用的内存的生存期。这意味着即使一个对象已经完成清理,扔可在它上面调用方法。以下代码演示了关闭后调用Write方法,试图想文件写入更多的字节,显示,这个字节再无法写入文件。代码执行时,对Write方法的第二个调用将抛出一个System.ObjectDisposedException异常,并显示以下字符创:无法访问已关闭的文件。

这里不会出现内存的损坏情况,因为FileStream对象的内存依然“健在”。只是在执行了清理之后,对象不能再成功的执行它的方法。

重要提示:我不赞成无脑的调用dispose和close方法。理由是CLR的垃圾回收期已经做得非常好了,理应把工作要给它去做。垃圾回收期知道一个对象何时不再调用应用程序的代码,而且只有到那个时候才会回收,而当应用程序调用dispose或Close方法时,实际实在信誓旦旦的说它知道应用程序在什么时候不需要一个对象,但对于应用程序来说,都不可能知道一个对象在什么时候不需要。

例如:假定在方法A的代码中构造一个新对象,然后将对该对象的引用传给方法B,方法B可能将对该对象的引用保存在某个内部字段变量中(一个根)。然而,方法A并不知道这个情况,它当然可以调用dispose和close方法,但在此之后,其它代码可能试图访问该对象,造成跑出一个ObjectDisposedException。

建议只有在以下这两种情况下才调用dispose或close:确定必须清理资源,或者确定可以安全的调用dispose或close,并希望将对象从终结列表中删除,禁止对象提供到另一代,从而提升性能。

时间: 2024-10-06 15:29:35

第七节:使用实现了dispose模式的类型的相关文章

[ExtJS学习笔记]第七节 Extjs的组件components及其模板事件方法学习

本文地址:http://blog.csdn.net/sushengmiyan/article/details/38487519 本文作者:sushengmiyan -------------------------------------------------------------资源链接----------------------------------------------------------------------- 翻译来源  Sencha Cmd官方网站: http://ww

CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第七节

第七节:使用下一代CUDA硬件,快乐加速度 原文链接 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并行运算的研究,并且是几个新创企业的合伙人.大家可以发邮件到[email protected]与他沟通和交流. 在关于CUDA(Compute Unified Device Architecture,即计算统一设备架构的简称)的系列文章的第六节,我探讨了使用CUDA PROFI

基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用

基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extjs的web表单设计器 第四节——控件拖放 基于Extjs的web表单设计器 第五节——数据库设计 基于Extjs的web表单设计器 第六节——界面框架设计 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式定义 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用

[转]改善C#程序的建议4:C#中标准Dispose模式的实现

需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不受CLR管理的对象,windows内核对象,如文件.数据库连接.套接字.COM对象等: 毫无例外地,如果我们的类型使用到了非托管资源,或者需要显式释放的托管资源,那么,就需要让类型继承接口IDisposable.这相当于是告诉调用者,该类型是需要显式释放资源的,你需要调用我的Dispose方法. 不

第七节 VMware View 6.0 菜鸟入门 Composer 安装和部署

第七节 VMware View 6.0 菜鸟入门 Composer 安装和部署 一.创建ComposerDB 数据库 在vc虚拟机中的数据库创建ComposerDB 创建ODBC,打开开始菜单--->管理工具---->数据源(ODBC) 二.安装View -Composer 软件 下载VMware-viewcomposer-6.0.1-2078421.exe 软件 输入域管理员的账户和密码 安装完后重启计算机

VUE2.0实现购物车和地址选配功能学习第七节

第七节 卡片选中,设置默认 1.卡片选中html:<li v-for="(item,index) in filterAddress" v-bind:class="{'check':index==currentIndex}" @click="currentIndex=index"> <!--循环判断currenIndex,控制当前选中卡片的样式-->js: data:{ currentIndex:0,},2.设置默认html

JAVA 从GC日志分析堆内存 第七节

JAVA 从GC日志分析堆内存 第七节 在上一章中,我们只设置了整个堆的内存大小.但是我们知道,堆又分为了新生代,年老代.他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比例大小能改变吗?其实这些都是可控的,以前没有讲到是因为就算讲了也只是讲讲而已,看不到实质性的东西.因此这章我们通过分析GC日志来一步步讲解如何细化设置堆内存. 首先我们来了解几个相关的参数: -XX:+PrintGCDetails:用于告诉虚拟机回收垃圾的时候顺便打印日志. -Xloggc:路径 :将打

centos mysql 优化 第七节课

centos mysql  优化  第七节课 f

C#中标准Dispose模式的实现

本文引自:http://www.cnblogs.com/luminji/archive/2011/03/29/1997812.html 需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不受CLR管理的对象,windows内核对象,如文件.数据库连接.套接字.COM对象等: 毫无例外地,如果我们的类型使用到了非托管资源,或者需要显式释放的托管资源,那