C#资源管理及IDisposable的实现Word下载.docx

上传人:b****2 文档编号:3061415 上传时间:2023-05-01 格式:DOCX 页数:19 大小:81.79KB
下载 相关 举报
C#资源管理及IDisposable的实现Word下载.docx_第1页
第1页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第2页
第2页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第3页
第3页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第4页
第4页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第5页
第5页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第6页
第6页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第7页
第7页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第8页
第8页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第9页
第9页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第10页
第10页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第11页
第11页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第12页
第12页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第13页
第13页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第14页
第14页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第15页
第15页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第16页
第16页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第17页
第17页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第18页
第18页 / 共19页
C#资源管理及IDisposable的实现Word下载.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

C#资源管理及IDisposable的实现Word下载.docx

《C#资源管理及IDisposable的实现Word下载.docx》由会员分享,可在线阅读,更多相关《C#资源管理及IDisposable的实现Word下载.docx(19页珍藏版)》请在冰点文库上搜索。

C#资源管理及IDisposable的实现Word下载.docx

析构函数提供了适当的保护,诸如自动调用基类的析构函数,在C#代码中,Object.Finalize不能被调用或重写

8.如果使用了非托管资源,那么需要通过析构函数来释放资源,也可以通过实现IDisposable的Dispose方式显示的释放资源。

如果使用了expensive的非托管资源,则推荐使用第二种方法。

9.Dispose方法应该释放所有的资源,同时也要调用其基类的Dispose方法释放其基类的所有资源

10.析构函数(Finalize)中不应该引用其他的对象,因为finalizer不能以一个特定的顺序执行。

11.在Dispose方法中不需要主动清理托管资源,但如果是实现了IDisposable的托管资源应该被清理,否则可能出现资源泄漏。

12.要总是避免直接调用GC.Collect方法。

2.相关概念

C#编程的一个优点就是程序员不需要关心具体的内存管理,垃圾收集器会处理所有的内存清理工作(?

)。

用户可以得到象C++语言那样的效率,而不需要考虑象C++那样内存管理的复杂性。

虽然不必要手工管理内存,但如果要编写高效的代码,仍需要理解后台是如何进行内存管理的。

在32位处理器上每个进程可以使用4GB的内存,不管计算机有多大的硬盘空间。

该4GB空间包含程序的所有部分,可执行代码、代码加载的所有DLL、程序运行使用的变量的内存。

这个4GB空间称为虚拟地址空间,或虚拟内存。

4GB中的每个存储单元都是从0开始往上排序的,要访问存储在内存的某个空间的一个值,就需要提供表示该存储单元的数字。

在进程的虚拟内存中,有一个称为堆栈的区域,它用来存储不是对象成员的值数据类型。

另外,在方法调用时,也使用堆栈复制传递给方法的所有参数。

堆栈指针(操作系统维护的一个变量)表示堆栈中下一个自由空间的地址。

程序第一次运行时,堆栈指针指向为堆栈保留的内存块末尾。

堆栈具有非常高的性能。

托管堆是进程可用空间的另一内存区域,它和C++使用的堆不同,它是在垃圾收集器(GarbageCollector)的控制下工作。

它用来为引用数据类型分配空间。

2.1IDisposable

IDisposable:

定义一个释放已分配的非托管资源的方法

Dispose:

IDisposable的唯一公共方法,执行与freeing,releasing或者resetting非托管资源相关的由应用程序定义的任务

在C#中,GC(Garbagecollector)会自动释放不再使用的托管对象,但是GC的调用时机是不能预知的。

而且,GC对于例如window句柄,打开的文件或流等非托管类资源无能为力。

Dispose方法与GC共同使用可以显示的释放非托管资源,对象的使用者可以在该对象不再使用的时候调用该方法释放资源。

当调用一个实现IDisposable接口的类时,使用try-finally模式确保即使在应用程序有异常发生时非托管资源仍然可以被释放。

●如果客户调用IDisposable.Dispose(),该客户就指定应清理所有与该对象相关的资源,包含托管和非托管资源。

●如果调用了析构函数,原则上所有的资源仍需要清理。

但是,析构函数必须由GC调用,而且不应该访问其他托管的对象。

2.2GarbageCollector

ms-help:

//MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_fxadvance/html/22b6cb97-0c80-4eeb-a2cf-5ed7655e37f9.htm

在.NETFramework中,GC为应用程序负责管理分配和释放内存。

每当使用new操作符创建对象时,运行库(runtime)就从托管堆上为对象分配内存。

只要管理堆上的地址空间是可获得的,运行库就继续为新对象分配空间。

然而,内存不是无限的,最后,GC为了释放内存必须执行回收操作。

GC的优化引擎决定了对已分配内存执行该操作的最佳时机。

当GC执行一个回收操作时,它首先检查托管堆上的对象不再被应用程序使用,然后执行必要的操作回收它的内存。

这里有一个推荐的设计模式用来在你创建应用程序时可以正确清除非托管资源。

GC:

控制系统垃圾回收器,一个自动回收无用内存的服务。

Themethodsinthisclassinfluencewhengarbagecollectionisperformedonanobject,andwhenresourcesallocatedbyanobjectarereleased.Propertiesinthisclassprovideinformationaboutthetotalamountofmemoryavailableinthesystemandtheagecategory,orgeneration,ofmemoryallocatedtoanobject.

Thegarbagecollectortracksandreclaimsobjectsallocatedinmanagedmemory.Periodically,thegarbagecollectorperformsgarbagecollectiontoreclaimmemoryallocatedtoobjectsforwhichtherearenovalidreferences.Garbagecollectionhappensautomaticallywhenarequestformemorycannotbesatisfiedusingavailablefreememory.Alternatively,anapplicationcanforcegarbagecollectionusingtheCollectmethod.

垃圾回收包含如下的几个步骤:

1.Thegarbagecollectorsearchesformanagedobjectsthatarereferencedinmanagedcode.

2.Thegarbagecollectorattemptstofinalizeobjectsthatarenotreferenced.

3.Thegarbagecollectorfreesobjectsthatarenotreferencedandreclaimstheirmemory.

Duringacollection,thegarbagecollectorwillnotfreeanobjectifitfindsoneormorereferencestotheobjectinmanagedcode.However,thegarbagecollectordoesnotrecognizereferencestoanobjectfromunmanagedcode,andmightfreeobjectsthatarebeingusedexclusivelyinunmanagedcodeunlessexplicitlypreventedfromdoingso.TheKeepAlivemethodprovidesamechanismthatpreventsthegarbagecollectorfromcollectingobjectsthatarestillinuseinunmanagedcode.

Asidefrommanagedmemoryallocations,implementationsofthegarbagecollectordonotmaintaininformationaboutresourcesheldbyanobject,suchasfilehandlesordatabaseconnections.Whenatypeusesunmanagedresourcesthatmustbereleasedbeforeinstancesofthetypearereclaimed,thetypecanimplementafinalizer.

Inmostcases,finalizersareimplementedbyoverridingtheObject.Finalizemethod;

however,typeswritteninC#orC++implementdestructors,whichcompilersturnintoanoverrideofObject.Finalize.Inmostcases,ifanobjecthasafinalizer,thegarbagecollectorcallsitpriortofreeingtheobject.However,thegarbagecollectorisnotrequiredtocallfinalizersinallsituations;

forexample,theSuppressFinalizemethodexplicitlypreventsafinalizerfrombeingcalled.Also,thegarbagecollectorisnotrequiredtouseaspecificthreadtofinalizeobjects,orguaranteetheorderinwhichfinalizersarecalledforobjectsthatreferenceeachotherbutareotherwiseavailableforgarbagecollection.

Inscenarioswhereresourcesmustbereleasedataspecifictime,classescanimplementtheIDisposableinterface,whichcontainstheIDisposable.Disposemethodthatperformsresourcemanagementandcleanuptasks.ClassesthatimplementDisposemustspecify,aspartoftheirclasscontract,ifandwhenclassconsumerscallthemethodtocleanuptheobject.Thegarbagecollectordoesnot,bydefault,calltheDisposemethod;

however,implementationsoftheDisposemethodcancallmethodsintheGCclasstocustomizethefinalizationbehaviorofthegarbagecollector.

Itisrecommended,butnotrequired,thatgarbagecollectorssupportobjectagingusinggenerations.Agenerationisaunitofmeasureoftherelativeageofobjectsinmemory.Thegenerationnumber,orage,ofanobjectindicatesthegenerationtowhichanobjectbelongs.Objectscreatedmorerecentlyarepartofnewergenerations,andhavelowergenerationnumbersthanobjectscreatedearlierintheapplicationlifecycle.Objectsinthemostrecentgenerationareingenerationzero.

2.3Finalize

//MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_fxadvance/html/fd376774-1643-499b-869e-9546a3aeea70.htm

对于应用程序创建的大多数对象来说,它们需要GC隐式的执行所有必要的内存管理任务。

然而,当创建了封装有非托管资源的对象时,则在应用程序使用完成后必须显示的释放这些非托管资源。

最常见的非托管资源类型是包含操作系统资源的对象,例如文件、窗口或者网络连接。

虽然,GC能够跟踪封装有非托管资源的对象的生命周期,但是它对于如何清理这些资源却无能为力。

对于这些类型的对象,.NETFramework提供了一个Object.Finalize方法,它允许在一个对象被GC要求回收它所使用的内存时,正确清理非托管资源。

一般情况下,Finalize什么都不作。

如果需要在回收该对象内存之前GC执行清理操作,你必须重写Finalize方法。

Note

ToimplementtheFinalizemethodinC#,youmustusedestructorsyntax.Inthe.NETFrameworkversion2.0,VisualC++providesitsownsyntaxforimplementingtheFinalizemethod,asdescribedinDestructorsandFinalizersinVisualC++.Inthe.NETFrameworkversion1.0and1.1,VisualC++useddestructorsyntaxfortheFinalizemethod,asC#does.

GC通过使用一个内部的finalization对列来保持对实现Finalize方法的对象的跟踪。

在应用程序创建了一个有Finalize方法的对象后,GC在finalization对列中存放指向该对象的一个入口。

Finalization对列包含托管堆上的所有的在GC回收它们内存之前调用它们自己的finalization代码的对象的入口。

Finalize不能抛出异常,因为应用程序不能处理这些异常,而且它们也会导致程序终止。

实现Finalize或者析构函数对于性能会有负面影响,所以在不必要时要避免这么做。

ReclaimingthememoryusedbyobjectswithFinalizemethodsrequiresatleasttwogarbagecollections.Whenthegarbagecollectorperformsacollection,itreclaimsthememoryforinaccessibleobjectswithoutfinalizers.Atthistime,itcannotcollecttheinaccessibleobjectsthatdohavefinalizers.Instead,itremovestheentriesfortheseobjectsfromthefinalizationqueueandplacestheminalistofobjectsmarkedasreadyforfinalization.Entriesinthislistpointtotheobjectsinthemanagedheapthatarereadytohavetheirfinalizationcodecalled.ThegarbagecollectorcallstheFinalizemethodsfortheobjectsinthislistandthenremovestheentriesfromthelist.Afuturegarbagecollectionwilldeterminethatthefinalizedobjectsaretrulygarbagebecausetheyarenolongerpointedtobyentriesinthelistofobjectsmarkedasreadyforfinalization.Inthisfuturegarbagecollection,theobjects'

memoryisactuallyreclaimed.

2.3.1Object.Finalize

允许对象在被GC回收前,尝试释放资源以及执行其他的清理操作。

C#

~Object()

Finalize是受保护的,它只能被该类和其继承类访问。

除非该对象被SuppressFinalize调用免除finalization,否则该方法在一个对象不可访问后会被自动调用。

在应用程序关闭期间,没有免除finalization操作的对象的Finalize会被自动调用,即使有些对象仍然是可访问的。

Finalize在一个对象上仅仅调用一次,除非使用诸如ReRegisterForFinalize的机制对该对象重新注册以及随后GC.SuppressFinalize没有被调用。

每一个继承类型的Finalize实现必须调用其基类的Finalize的实现。

这是一种唯一的情况,应用程序允许调用Finalize。

Finalize有如下的限制:

●Finalizer的确切执行时间是不确定的。

●两个对象的finalizer不能保证以一个的指定的顺序执行,即使一个对象引用了另一个对象。

也就是说,如果对象A应用了对象B,并且它们都实现了finalizer,在对象A开始finalizer时对象B可能已经finalizer了。

●Finalizer在哪个线程上运行也使不确定的

在如下的异常情况下,Finalize方法可能不被完整执行或者根本不能执行:

●其他的finalizer无限期的阻塞(进入一个无限期的循环,尝试获得一个不可能得到的锁等等)。

●在没有给运行库机会进行清理时,进城已经终止了。

这种情况下,运行苦的第一个进程终止通知是一个DLL_PROCESS_DETACH。

仅仅当finalizable对象的数量持续减少时,运行库才会继续在关闭期间继续finalize对象。

如果finalize或者一个finalize的重写抛出异常,andtheruntimeisnothostedbyanapplicationthatoverridesthedefaultpolicy,theruntimeterminatestheprocessandnoactivetry-finallyblocksorfinalizersareexecuted.Thisbehaviorensuresprocessintegrityifthefinalizercannotfreeordestroyresources.

实现的注意事项:

Object.Finalize默认什么也不做。

仅在必要时,继承类必须重写该方法,因为如果finalize必须执行的话,GC的回收趋向花费更长的时间。

如果一个对象持有任何资源的引用,Finalize必须被继承类重写,用来在GC丢弃该对象之前释放这些资源。

使用了非托管资源的类型必须实现Finalize,例如文件句柄、数据库连接等非托管资源在使用它们的对象被回收时必须被释放。

请查看IDisposable接口获取补充的和更多的处理资源的控制方法。

Finalize可以执行任何动作,包括一个对象已经在垃圾回收期间被清除后复活一个对象(让这个对象可再次访问)。

然后,这个对象仅仅能够被复活一次;

再垃圾回收期间,复活对象的Finalize不能被调用。

在C#中,析构函数用来执行清理操作。

析构函数提供了适当的保护,诸如自动调用基类的析构函数,在C#代码中,Object.Finalize不能被调用或重写。

2.4Destructor

//MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_csref/html/1ae6e46d-a4b1-4a49-abe5-b97f53d9e049.htm

析构函数用来销毁类的实例。

●结构体中不能定义析构函数,析构函数仅用在类中。

●一个类仅能有一个析构函数。

●析构函数不能被继承以及重载

●析构函数不能被调用,是自动调用(invoke)的

●析构函数不能有任何修饰或者参数

析构函数隐式的调用基类的Finalize,因此,如上图左边的析构函数代码会隐式的翻译成右边的形式。

对于继承链上的所有实例Finalize方法会从most-derived到least-derived被递归调用。

注意

空析构函数不能被使用。

当一个类包含有析构函数,Finalize队列会为其创建一个入口。

当析构函数被调用时,GC会被启动来处理这个队列。

如果析构函数是空的,这会导致不必要的性能损失。

程序员不能控制析构函数的调用,它是由GC决定的。

析构函数也在程序退出时被调用。

也可以强制GC回收,但在大多数情况下不能这样做,这会导致性能问题。

使用析构函数释放资源

一般来讲,C#不要求太多的内存管理,因为GC隐式的管理着内存的分配和释放。

然而,如果封装了非托管资源,例如文件、窗口、网络链接等,则必须使用析构函数释放这些资源。

当一个对象成为要销毁的对象时,GC会执行该对象

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 生物学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2