第七节:使用实现了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,并希望将对象从终结列表中删除,禁止对象提供到另一代,从而提升性能。
第七节:使用实现了dispose模式的类型的更多相关文章
- delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行
第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行 以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...
- centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpfs ,nr_inodes, LVM,传统方式扩容文件系统 第七节课
centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpf ...
- CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第七节
第七节:使用下一代CUDA硬件,快乐加速度 原文链接 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个 ...
- 【C# .Net GC】清除非托管类型(Finalize终结器、dispose模式以及safeHandler)
总结 1.一般要获取一个内核对象的引用,最好用SafeHandle来引用它,这个类可以帮你管理引用计数,而且用它引用内核对象,代码更健壮 2.托管中生成并引用非托管,一但非托管和托管中的引用断开(托管 ...
- C#中标准Dispose模式的实现与使用(条目17 实现标准的销毁模式)
实现了Dispose模式与实现了IDisposable接口的区别就是:IDisposable的实现的可靠性(释放相关资源)要靠编程人员来解决(你确信你从来都一直调用了Dispose(Close)方法吗 ...
- [学习笔记] Dispose模式
Dispose模式是.NET中很基础也很重要的一个模式,今天重新复习一下相关的东西并记录下来. 什么是Dispose模式? 什么时候我们该为一个类型实现Dispose模式 使用Dispose模式时应该 ...
- 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用
基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extj ...
- C#中标准Dispose模式的实现
http://www.cnblogs.com/luminji/archive/2011/03/29/1997812.html 需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个 ...
- JAVA 从GC日志分析堆内存 第七节
JAVA 从GC日志分析堆内存 第七节 在上一章中,我们只设置了整个堆的内存大小.但是我们知道,堆又分为了新生代,年老代.他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比 ...
随机推荐
- 共享池之八:软解析、硬解析、软软解析 详解一条SQL在library cache中解析涉及的锁
先来张大图: 结合上图来说明一下解析的各个步骤涉及的锁. 软解析.硬解析.软软解析区别的简单说明: 为了将用户写的sql文本转化为oracle认识的且可执行的语句,这个过程就叫做解析过程. 解析分为硬 ...
- OC基础(23)
NSArray基本概念 NSArray 遍历 NSArray排序 NSArray文件读写 NSArray 与字符串 *:first-child { margin-top: 0 !important; ...
- python 简单实现文件拷贝
1.背景 一日加班需要写一个文件拷贝的函数. 写了几版拷贝函数,有需要的直接粘贴过去 def CopyLocaleFile1(sorfile,desfile): #第一版 sorfp=open(sor ...
- .net Url重写
详细说明及下载dll源码路径: http://msdn.microsoft.com/zh-cn/library/ms972974.aspx 顺带上本人写的一个小例子:http://files.cnbl ...
- 匿名管道 远程cmd
管道是单向的,传送数据的方向是固定的,所以互相通信需要两个管道. STARTUPINFO si; ZeroMemory(&si,sizeof(si)); si.dwFlags = STARTF ...
- C# 操作XML 如果不存在创建 存在直接追加
#region 写操作日志----------------这种格式 //<Log 操作人="Admin" 操作结果="成功" 结果详情="数据导 ...
- jquery ajax 保存讲解
jquery ajax 参数传递与数据保存实例是一款适合于初学者用的,首先我们是讲一下关于如何利用ajax +php进行数据操作,然后再详细的介绍关于jquery ajax的帮助说明. jquery ...
- C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)
C#图像处理 (各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果) 一.各种旋转.改变大小 注意:先要添加画图相关的using引用. //向右旋转图像90°代码如下 ...
- hadoop,hbase,pig安装
注意端口,办公网只能访问8000-9000的端口 pig的一些lib文件版本 /home/map/hadoop/lib下一些98.5的lib没删除
- IEF could not decode Chinese character in IE history well
My friend is working on some case, and she looks not in the mood. I ask her what's going on. She wan ...