第七节:使用实现了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,他们的比 ...
随机推荐
- OC基础(1)
Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 *:first-child { margin-top: 0 !important; } body > *:last-chi ...
- The Ninth Hunan Collegiate Programming Contest (2013) Problem C
Problem C Character Recognition? Write a program that recognizes characters. Don't worry, because yo ...
- 使用django表单,使网页添加上传文件,并分析文件。
开发环境是: apache + python + django+ eclipse(开发环境) 欲达到目的: 在网页上,添加上传文件控件.然后读取csv文件,并分析csv文件. 操作步骤: django ...
- 2014款Macbook Air安装单独X64 Win7系统
之所以写出来,是因为网上大多是用BootCamp安装双系统的,安装单独Win7的教程少之又少,然后大多数还写得不清不楚,所以折腾了一阵子.其实装好之后,还是觉得挺简单的. 我主要参考了两篇文章,链接如 ...
- Debian的一个命令
dpkg是一个Debian的一个命令行工具,它可以用来安装.删除.构建和管理Debian的软件包.下面是它的一些命令解释:1)安装软件命令行:dpkg -i <.deb file name> ...
- linx 实用操作命令二
pcre相关操作pcretest -C #查看pcre是否支持utf8 rpm -q -a #查看软件包列表rpm -ql pcre-7.8-6.el6.x86_64 #查看包安装的位置rpm -e ...
- MVC中使用过滤器记录异常日志
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Filte ...
- UITableView 详解 ()
(原本取至D了个L微信公众号) UITableView 详解 一.建立 UITableView DataTable = [[UITableView alloc] initWithFrame:CGRec ...
- Leetcode049. Group Anagrams
//hashmap implement with STL class Solution { public: vector<vector<string>> groupAnagra ...
- EasyUI学习笔记
1,tabs获得被选中的标题 var tabTitle = $('#tabs').tabs('getSelected').panel('options').title;//获得被选中的标题 2.当设置 ...