



下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在.net编程环境中,系统的资源分为托管资源和非托管资源。对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的只是了解netCLR如何做这些操作。也就是说对于您的应用程序创建的大多数对象,可以依靠.NETFramework的垃圾回收器隐式地执行所有必要的内存管理任务。资源分为两种,托管的内存资源,这是不需要我们操心的,系统已经为我们进行管理了;那么对于非托管的资源,这里再重申一下,就是Stream,数据库的连接,GDI+的相关对象,还有Com对象等等这些资源,需要我们手动去释放。对于非托管资源,您在应用程序中使用完这些非托管资源之后,必须显示的释放他们,例如System.IO.StreamReader的一个文件对象,必须显示的调用对象的Close()方法关闭它,否则会占用系统的内存和资源,而且可能会出现意想不到的错误。我想说到这里,一定要清楚什么是托管资源,什么是非托管资源了?释放。最常见的一类非托管资源就是包装操作系统资源的对象,例如文件,窗口或网络连接,对于这类资源虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理这些资源。还好.netFramework提供了Finalize()方法,它允许在垃圾回收器回收该类资源时,适当的清理非托管资源。如果在MSDNLibrary中搜索Finalize将会发现很多类似的主题,这里列举几种常见的非托管资源:ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,Timer,Tooltip等等资源。可能在使用的时候很多都没有注意到!关于托管资源,就不用说了撒,像简单的int,string,float,DateTime等等,.net中超过80%的资源都是托管资源。非托管资源如何释放,.NETFramework提供Object.Finalize方法,它允许对象在垃圾回收器回收该对象使用的内存时适当清理其非托管资源。默认情况下,Finalize方法不执行任何操作。默认情况下,Finalize方法不执行任何操作。如果您要让垃圾回收器在回收对象的内存之前对对象执行清理操作,您必须在类中重写Finalize方法。然而大家都可以发现在实际的编程中根本无法override方法Finalize(),在C#中,可以通过析构函数自动生成Finalize方法和对基类的Finalize方法的调用。例如:~MyClass(){//Performsomecleanupoperationshere.}该代码隐式翻译为下面的代码。protectedoverridevoidFinalize(){try{//Performsomecleanupoperationshere.}finally{base.Finalize();}}但是,在编程中,并不建议进行override方法Finalize。,因为,实现Finalize方法或析构函数对性能可能会有负面影响。一个简单的理由如下:用Finalize方法回收对象使用的内存需要至少两次垃圾回收,当垃圾回收器回收时,它只回收没有终结器(Finalize方法)的不可访问的内存,这时他不能回收具有终结器(Finalize方法)的不可以访问的内存。它改为将这些对象的项从终止队列中移除并将他们放置在标记为'准备终止”的对象列表中,该列表中的项指向托管堆中准备被调用其终止代码的对象,下次垃圾回收器进行回收时,就回收并释放了这些内存。C#托管及未托管对象管理C#中的对象分为值类型和引用类型,二者最大的区别在于数据的存储方式和存储位置.WINDOWS操作系统使用虚拟寻址系统来管理程序运行时产生的数据存放.简单的说,该系统管理着一个内存区域,在该区域中划拨出一部分出来专门存放值类型变量,称为堆栈,堆栈采用先进后出的原则,将值类型变量从区域的最高地址位开始向低位地址存储,先进后出,后进先出的管理方式保证了值类型变量在出了作用域后能即使的清除占用的内存区域由于堆栈速度快,所保存的数据一般不太大,这部分一般不需要用户专门操作.值类型保存在堆栈汇总,堆栈有非常高的性能,但对于所有的变量来说还是不太灵活。通常我们希望使用一个方法分配内存,来存储一些数据,并在方法退出后的很长一段时间内数据仍是可以使用的。只要是用new运算符来请求存储空间,就存在这种可能*一例如所有的引用类型。此时就要使用托管堆。它在垃圾收集器的控制下工作,托管堆(或简称为堆)是系统管理的大内存区域中的另一个内存区域。要了解堆的工作原理和如何为引用数据类型分配内存,看看下面的代码:Customerarabel=newCustomer();这行代码完成了以下操作:首先,分配堆上的内存,以存储Customer实例(一个真正的实例,不只是一个地址)。然后把变量arabel的值设置为分配给新Customer对象的内存地址(它还调用合适的Customer。构造函数初始化类实例中的字段,但我们不必担心这部分)。Customer实例没有放在堆栈中,而是放在内存的堆中。如果我们这样操作:Customernewaddress=arabel;这时候,newaddress也会保存在堆栈中,其值和arabel相同,都是存储Customer实例的堆地址.知道了这些,我们会发现这样一个问题,如果堆栈中arabel和newaddress两个变量过期销毁,那堆中保存的Customer对象会怎样?实际上它仍保留在堆中,一直到程序停止,或垃圾收集器删除它为止.C#的垃圾收集器如果没有显示调用,会定时运行并检查内存,删除没有任何变量引用的数据.看起来似乎不错,但是想想,垃圾回收器并不是时时检查,它是定时运行,而在这段时间内如果产生大量的过期数据驻留在内存中..•.•那么或许我们可以通过调用System.GC.Collect(),强迫垃圾收集器在代码的某个地方运行,System.GC是一个表示垃圾收集器的.NET基类,Collect()方法则调用垃圾收集器。但是,这种方式适用的场合很少,(难道销毁一个对象就让垃圾回收检查一便内存吗?)例如,代码中有大量的对象刚刚停止引用,就适合调用垃圾收集器。况且垃圾收集器的逻辑不能保证在一次垃圾收集过程中,从堆中删除所有过期数据,对于不受垃圾回收器管理的未托管对象(例如文件句柄、网络连接和数据库连接)它是无能为力的。那该怎么做呢?这时需要制定专门的规则,确保未托管的资源在回收类的一个实例时释放。在定义一个类时,可以使用两种机制来自动释放未托管的资源。这些机制常常放在一起实现,因为每个机制都为问题提供了略为不同的解决方法。这两个机制是:声明一个析构函数,作为类的一个成员在类中实现System.IDisposable接口下面依次讨论这两个机制,然后介绍如何同时实现它们,以获得最佳的效果。析构函数前面介绍了构造函数可以指定必须在创建类的实例时进行的某些操作,在垃圾收集器删除对象时,也可以调用析构函数。由于执行这个操作,所以析构函数初看起来似乎是放置释放未托管资源、执行一般清理操作的代码的最佳地方。但是,事情并不是如此简单。由于垃圾回首器的运行规则决定了,不能在析构函数中放置需要在某一时刻运行的代码,如果对象占用了宝贵而重要的资源,应尽可能快地释放这些资源,此时就不能等待垃圾收集器来释放了.IDisposable接口一个推荐替代析构函数的方式是使用System.IDisposable接口"Disposable接口定义了一个模式(具有语言级的支持),为释放未托管的资源提供了确定的机制,并避免产生析构函数固有的与垃圾函数器相关的问题。IDisposable接口声明了一个方法Dispose。,它不带参数,返回void,Myclass的方法Dispose()的执行代码如下:classMyclass:IDisposable{publicvoidDispose(){//implementation}}Dispose()的执行代码显式释放由对象直接使用的所有未托管资源,并在所有实现[Disposable接口的封装对象上调用Dispose。。这样,Dispose()方法在释放未托管资源时提供了精确的控制。假定有一个类ResourceGobbler,它使用某些外部资源,且执行[Disposable接口。如果要实例化这个类的实例,使用它,然后释放它,就可以使用下面的代码:ResourceGobblerthelnstance=newResourceGobbler();//这里是thelnstance对象的使用过程theInstance.Dispose();如果在处理过程中出现异常,这段代码就没有释放thelnstance使用的资源,所以应使用try块,编写下面的代码:ResourceGobblerthelnstance=null;try{thelnstance=newResourceGobbler();//这里是thelnstance对象的使用过程}finally{if(thelnstance!=null)thelnstance.Dispose();}即使在处理过程中出现了异常,这个版本也可以确保总是在thelnstance上调用Dispose。,总是释放由thelnstance使用的资源。但是,如果总是要重复这样的结构,代码就很容易被混淆。C#提供了一种语法,可以确保在引用超出作用域时,在对象上自动调用Dispose()(但不是Close())。该语法使用了using关键字来完成这一工作但目前,在完全不同的环境下,它与命名空间没有关系。下面的代码生成与try块相对应的lL代码:using(ResourceGobblerthelnstance=newResourceGobbler()){//这里是thelnstance对象的使用过程}using语句的后面是一对圆括号,其中是引用变量的声明和实例化,该语句使变量放在随附的复合语句中。另外,在变量超出作用域时,即使出现异常,也会自动调用其Dispose。方法。如果已经使用try块来捕获其他异常,就会比较清晰,如果避免使用using语句,仅在已有的try块的finally子句中调用Dispose。,还可以避免进行额外的缩进。注意:对于某些类来说,使用Close()要比Dispose()更富有逻辑性,例如,在处理文件或数据库连接时,就是这样。在这些情况下,常常实现lDisposable接口,再执行一个独立的Close()方法,来调用Dispose。。这种方法在类的使用上比较清晰,还支持C#提供的using语句。前面的章节讨论了类所使用的释放未托管资源的两种方式:•利用运行库强制执行的析构函数,但析构函数的执行是不确定的,而且,由于垃圾收集器的工作方式,它会给运行库增加不可接受的系统开销。lDisposable接口提供了一种机制,允许类的用户控制释放资源的时间,但需要确保执行Dispose。。一般情况下,最好的方法是执行这两种机制,获得这两种机制的优点,克服其缺点。假定大多数程序员都能正确调用Dispose。,实现IDisposable接口,同时把析构函数作为一种安全的机制,以防没有调用Dispose。。下面是一个双重实现的例子:publicclassResourceHolder:IDisposable{privateboolisDispose=false;//Pointertoanexternalunmanagedresource.privateIntPtrhandle;//Othermanagedresourcethisclassuses.privateComponentComponents;//显示调用的Dispose方法publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}//实际的清除方法protectedvirtualvoidDispose(booldisposing){if(!isDisposed){if(disposing){//这里执行清除托管对象的操作.}//这里执行清除非托管对象的操作CloseHandle(handle);handle=IntPtr.Zero;}isDisposed=true;}//析构函数~ResourceHolder(){Dispose(false);}}可以看出,Dispose()有第二个protected重载方法,它带一个bool参数,这是真正完成清理工作的方法。Dispose(bool)由析构函数和IDisposable.Dispose()调用。这个方式的重点是确保所有的清理代码都放在一个地方。传递给Dispose(bool)的参数表示Dispose(b
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- LY/T 2762-2024黄精
- 2025至2030年中国平衡重式电动车数据监测研究报告
- 2025至2030年中国PVC防静电胶地板数据监测研究报告
- 【假期提升】 五升六语文暑假作业(十三)-人教部编版(含答案含解析)
- 2025年消防设施操作员之消防设备中级技能提升训练试卷A卷附答案
- 城步中考数学试题及答案
- 采购与制造分包合同(2篇)
- 高等教育自学考试《00102世界市场行情》模拟试卷二
- 2024年广东省公务员《申论(省市级)》试题真题及答案
- 内燃机基础知识培训课件
- 2025年天翼云解决方案架构师认证考试指导题库-上(单选题)
- 2025年广东省深圳市高考语文一模试卷
- 2025年春人教版英语八年级下册同步课件 Unit 7 Whats the highest mountain in the world课件 Section A 1a-2d
- 2025年哈尔滨铁道职业技术学院单招职业倾向性测试题库必考题
- 行为规范教育中学校长在国旗下讲话:严格要求自己规范自己的行为
- 2025年福建省高职单招职业适应性测试题库及答案解析
- 七下综合世界真奇妙-共享“地球村”
- 自媒体运营实战教程(抖音版) 课件 第7章 短视频运营-自媒体中级
- 2025年信阳职业技术学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 2025-2030年中国eva热熔胶行业运营状况与发展潜力分析报告
- 2024年广东职业技术学院高职单招语文历年参考题库含答案解析
评论
0/150
提交评论