版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Using of Memory (Managed and Unmanaged Resource)Zhou yuhui 2007-12-111.结论堆栈区用来存储值数据类型,以及方法调用中的所有参数的复制。托管堆和C+中的堆不同,它用来存储引用数据类型。GC能够自动释放托管资源,但是无法确定GC的调用时机GC对于OS资源无能为力, 例如文件、窗口等。.NET Framework提供了一个Object.Finalize方法,它允许在一个对象被GC要求回收它 所使用的内存时,正确清理非托管资源。在C#中,Finalize即是析构函数,它的使用有损性能。Finalizer的确切执行时间是不确定的。资源
2、不能保证在一个指定的时刻被释放,除了 调用了 Close方法或者Dispose方法在C#中,析构函数用来执行清理操作。析构函数提供了适当的保护,诸如自动调用基 类的析构函数,在C#代码中,Object.Finalize不能被调用或重写如果使用了非托管资源,那么需要通过析构函数来释放资源,也可以通过实现 IDisposable的Dispose方式显示的释放资源。如果使用了 expensive的非托管资源,则 推荐使用第二种方法。Dispose方法应该释放所有的资源,同时也要调用其基类的Dispose方法释放其基类的 所有资源析构函数(Finalize)中不应该引用其他的对象,因为finalize
3、r不能以一个特定的顺序 执行。在Dispose方法中不需要主动清理托管资源,但如果是实现了 IDisposable的托管资源 应该被清理,否则可能出现资源泄漏。要总是避免直接调用GC.Collect方法。2.相关概念C#编程的一个优点就是程序员不需要关心具体的内存管理,垃圾收集器会处理所有的 内存清理工作(?)。用户可以得到象C+语言那样的效率,而不需要考虑象C+那样内存管 理的复杂性。虽然不必要手工管理内存,但如果要编写高效的代码,仍需要理解后台是如何 进行内存管理的。在32位处理器上每个进程可以使用4GB的内存,不管计算机有多大的硬盘空间。该 4GB空间包含程序的所有部分,可执行代码、代码
4、加载的所有DLL、程序运行使用的变量 的内存。这个4GB空间称为虚拟地址空间,或虚拟内存。4GB中的每个存储单元都是从0开始往上排序的,要访问存储在内存的某个空间的一 个值,就需要提供表示该存储单元的数字。在进程的虚拟内存中,有一个称为堆栈的区域,它用来存储不是对象成员的值数据类型。 另外,在方法调用时,也使用堆栈复制传递给方法的所有参数。堆栈指针(操作系统维护的 一个变量)表示堆栈中下一个自由空间的地址。程序第一次运行时,堆栈指针指向为堆栈保 留的内存块末尾。堆栈具有非常高的性能。托管堆是进程可用空间的另一内存区域,它和C+使用的堆不同,它是在垃圾收集器 (Garbage Collecto
5、r)的控制下工作。它用来为引用数据类型分配空间。IDisposableIDisposable:定义一个释放已分配的非托管资源的方法Dispose: IDisposable 的唯一公共方法,执行与 freeing, releasing 或者 resetting 非托管 资源相关的由应用程序定义的任务在C#中,GC(Garbage collector)会自动释放不再使用的托管对象,但是GC的调用时机 是不能预知的。而且,GC对于例如window句柄,打开的文件或流等非托管类资源无能为 力。Dispose方法与GC共同使用可以显示的释放非托管资源,对象的使用者可以在该对 象不再使用的时候调用该方法释
6、放资源。当调用一个实现IDisposable接口的类时,使用try-finally模式确保即使在应用程序有异 常发生时非托管资源仍然可以被释放。如果客户调用IDisposable.Dispose(),该客户就指定应清理所有与该对象相关的资 源,包含托管和非托管资源。如果调用了析构函数,原则上所有的资源仍需要清理。但是,析构函数必须由GC 调用,而且不应该访问其他托管的对象。Garbage Collectorms-help:/MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_fxadvance/html/22b6cb97-0c80-4eeb-a2cf-5ed7655e37
7、f9.htm在.NET Framework中,GC为应用程序负责管理分配和释放内存。每当使用new操作 符创建对象时,运行库(runtime)就从托管堆上为对象分配内存。只要管理堆上的地址空间是 可获得的,运行库就继续为新对象分配空间。然而,内存不是无限的,最后,GC为了释放 内存必须执行回收操作。GC的优化引擎决定了对已分配内存执行该操作的最佳时机。当 GC执行一个回收操作时,它首先检查托管堆上的对象不再被应用程序使用,然后执行必要 的操作回收它的内存。这里有一个推荐的设计模式用来在你创建应用程序时可以正确清除非托管资源。GC :控制系统垃圾回收器,一个自动回收无用内存的服务。The met
8、hods in this class influence when garbage collection is performed on an object, and when resources allocated by an object are released. Properties in this class provide information about the total amount of memory available in the system and the age category, or generation, of memory allocated to an
9、 object.The garbage collector tracks and reclaims objects allocated in managed memory. Periodically, the garbage collector performs garbage collection to reclaim memory allocated to objects for which there are no valid references. Garbage collection happens automatically when a request for memory ca
10、nnot be satisfied using available free memory. Alternatively, an application can force garbage collection using the Collect method.垃圾回收包含如下的几个步骤:The garbage collector searches for managed objects that are referenced in managed code.The garbage collector attempts to finalize objects that are not refe
11、renced.The garbage collector frees objects that are not referenced and reclaims their memory.During a collection, the garbage collector will not free an object if it finds one or more references to the object in managed code. However, the garbage collector does not recognize references to an object
12、from unmanaged code, and might free objects that are being used exclusively in unmanaged code unless explicitly prevented from doing so. The KeepAlive method provides a mechanism that prevents the garbage collector from collecting objects that are still in use in unmanaged code.Aside from managed me
13、mory allocations, implementations of the garbage collector do not maintain information about resources held by an object, such as file handles or database connections. When a type uses unmanaged resources that must be released before instances of the type are reclaimed, the type can implement a fina
14、lizer.In most cases, finalizers are implemented by overriding theObject.Finalize method; however, types written in C# or C+ implement destructors, which compilers turn into an override of Object.Finalize. In most cases, if an object has a finalizer, the garbage collector calls it prior to freeing th
15、e object. However, the garbage collector is not required to call finalizers in all situations; for example, the SuppressFinalize method explicitly prevents a finalizer from being called. Also, the garbage collector is not required to use a specific thread to finalize objects, or guarantee the order
16、in which finalizers are called for objects that reference each other but are otherwise available for garbage collection.In scenarios where resources must be released at a specific time, classes can implement the IDisposable interface, which contains the IDisposable.Dispose method that performs resou
17、rce management and cleanup tasks. Classes that implement Dispose must specify, as part of their class contract, if and when class consumers call the method to clean up the object. The garbage collector does not, by default, call the Dispose method; however, implementations of the Dispose method can
18、call methods in the GC class to customize the finalization behavior of the garbage collector.It is recommended, but not required, that garbage collectors support object aging using generations. A generation is a unit of measure of the relative age of objects in memory. The generation number, or age,
19、 of an object indicates the generation to which an object belongs. Objects created more recently are part of newer generations, and have lower generation numbers than objects created earlier in the application life cycle. Objects in the most recent generation are in generation zero.Finalizems-help:/
20、MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_fxadvance/html/fd376774-1643-499b-869e-9546a3aeea 70.htm对于应用程序创建的大多数对象来说,它们需要GC隐式的执行所有必要的内存管理任 务。然而,当创建了封装有非托管资源的对象时,则在应用程序使用完成后必须显示的释放 这些非托管资源。最常见的非托管资源类型是包含操作系统资源的对象,例如文件、窗口或 者网络连接。虽然,GC能够跟踪封装有非托管资源的对象的生命周期,但是它对于如何清 理这些资源却无能为力。对于这些类型的对象,.NET Framework提供了一个Object
21、.Finalize 方法,它允许在一个对象被GC要求回收它所使用的内存时,正确清理非托管资源。一般情 况下,Finalize什么都不作。如果需要在回收该对象内存之前GC执行清理操作,你必须重 写 Finalize 方法。iNoteTo implement the Finalize method in C#, you must use destructor syntax. In the .NET Framework version 2.0, Visual C+ provides its own syntax for implementing the Finalize method, as des
22、cribed in Destructors and Finalizers in Visual C+ + . In the .NET Framework version 1.0 and 1.1, Visual C+ used destructor syntax for the Finalize method, as C# does.GC通过使用一个内部的finalization对列来保持对实现Finalize方法的对象的跟踪。在 应用程序创建了 一个有Finalize方法的对象后,GC在finalization对列中存放指向该对象的 一个入口。Finalization对列包含托管堆上的所有的在G
23、C回收它们内存之前调用它们自己的 finalization代码的对象的入口。Finalize不能抛出异常,因为应用程序不能处理这些异常,而且它们也会导致程序终止。 实现Finalize或者析构函数对于性能会有负面影响,所以在不必要时要避免这么做。Reclaiming the memory used by objects with Finalize methods requires at least two garbage collections. When the garbage collector performs a collection, it reclaims the memory f
24、or inaccessible objects without finalizers. At this time, it cannot collect the inaccessible objects that do have finalizers. Instead, it removes the entries for these objects from the finalization queue and places them in a list of objects marked as ready for finalization. Entries in this list poin
25、t to the objects in the managed heap that are ready to have their finalization code called. The garbage collector calls the Finalize methods for the objects in this list and then removes the entries from the list. A future garbage collection will determine that the finalized objects are truly garbag
26、e because they are no longer pointed to by entries in the list of objects marked as ready for finalization. In this future garbage collection, the objects memory is actually reclaimed.2.3.1 Object.Finalize允许对象在被GC回收前,尝试释放资源以及执行其他的清理操作。C#Object()Finalize是受保护的,它只能被该类和其继承类访问。除非该对象被SuppressFinalize调用免除f
27、inalization,否则该方法在一个对象不可 访问后会被自动调用。在应用程序关闭期间,没有免除finalization操作的对象的Finalize 会被自动调用,即使有些对象仍然是可访问的。Finalize在一个对象上仅仅调用一次,除 非使用诸如ReRegisterForFinalize的机制对该对象重新注册以及随后 GC.SuppressFinalize 没有被调用。每一个继承类型的Finalize实现必须调用其基类的Finalize的实现。这是一种唯一的 情况,应用程序允许调用Finalize。Finalize有如下的限制:Finalizer的确切执行时间是不确定的。资源不能保证在一个
28、指定的时刻被释放, 除了调用了 Close方法或者Dispose方法两个对象的finalizer不能保证以一个的指定的顺序执行,即使一个对象引用了另 一个对象。也就是说,如果对象A应用了对象B,并且它们都实现了 finalizer, 在对象A开始finalizer时对象B可能已经finalizer 了。Finalizer在哪个线程上运行也使不确定的在如下的异常情况下,Finalize方法可能不被完整执行或者根本不能执行:其他的finalizer无限期的阻塞(进入一个无限期的循环,尝试获得一个不可能得 到的锁等等)。在没有给运行库机会进行清理时,进城已经终止了。这种情况下,运行苦的第一个 进程终
29、止通知是一个DLL_PROCESS_DETACH。仅仅当finalizable对象的数量持续减少时,运行库才会继续在关闭期间继续finalize 对象。如果 finalize 或者一个 finalize 的重写抛出异常,and the runtime is not hosted by an application that overrides the default policy, the runtime terminates the process and no active try-finally blocks or finalizers are executed. This behavi
30、or ensures process integrity if the finalizer cannot free or destroy resources.实现的注意事项:Object.Finalize默认什么也不做。仅在必要时,继承类必须重写该 方法,因为如果finalize必须执行的话,GC的回收趋向花费更长的时间。如果一个对象持 有任何资源的引用,Finalize必须被继承类重写,用来在GC丢弃该对象之前释放这些资源。 使用了非托管资源的类型必须实现Finalize,例如文件句柄、数据库连接等非托管资源在使 用它们的对象被回收时必须被释放。请查看IDisposable接口获取补充的和更
31、多的处理资 源的控制方法。Finalize可以执行任何动作,包括一个对象已经在垃圾回收期间被清除后复 活一个对象(让这个对象可再次访问)。然后,这个对象仅仅能够被复活一次;再垃圾回收期 间,复活对象的Finalize不能被调用。在C#中,析构函数用来执行清理操作。析构函数提供了适当的保护,诸如自动调用基 类的析构函数,在C#代码中,ObjectFinalize不能被调用或重写。2.4 Destructorms-help:/MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_csref/html/1ae6e46d-a4b1-4a49-abe5-b97f53d9e049.htm
32、析构函数用来销毁类的实例。结构体中不能定义析构函数,析构函数仅用在类中。一个类仅能有一个析构函数。析构函数不能被继承以及重载析构函数不能被调用,是自动调用(invoke析构函数不能有任何修饰或者参数匚#pxotectedi ovectlde vcild Finalize ()class Car/ cleanup stateiients. - Erf) / destructortlnally/ cleanup sMcenents1 析构函数隐式的调用基类的Finalize,因此,如上图左边的析构函数代码会隐式的翻译 成右边的形式。对于继承链上的所有实例Finalize方法会从most-deriv
33、ed到 least-derived被递归调用。阿注意空析构函数不能被使用。当一个类包含有析构函数,Finalize队列会为其创建一个入口。 当析构函数被调用时,GC会被启动来处理这个队列。如果析构函数是空的,这会导致不 必要的性能损失。程序员不能控制析构函数的调用,它是由GC决定的。析构函数也在程序退出时被调用。 也可以强制GC回收,但在大多数情况下不能这样做,这会导致性能问题。使用析构函数释放资源一般来讲,C#不要求太多的内存管理,因为GC隐式的管理着内存的分配和释放。然 而,如果封装了非托管资源,例如文件、窗口、网络链接等,则必须使用析构函数释放这些 资源。当一个对象成为要销毁的对象时,G
34、C会执行该对象的Finalize方法。显示的释放资源如果应用程序使用了比较浪费(expensive)的外部资源,则推荐提供一个方法在GC释放 该对象之前释放这些资源。通过实现IDisposable的Dispose方法执行必要的清理动作可以实 现显示的释放资源。这能够很好的提高应用程序的性能。即使是显示的控制资源,析构函数 也可以在调用Dispose失败后清理资源。3.实现 Disposems-help:/MS.MSSDK.1033/MS.NETFX30SDK.1033/dv_fxadvance/html/eb4e1af0-3b48-4fbc-ad 4e-fc2f64138bf9.htm根据以上
35、的调查结论,如果使用了非托管资源,那么需要通过析构函数来释放资源, 也可以通过实现IDisposable的Dispose方式显示的释放资源。如果使用了 expensive的非托 管资源,则推荐使用第二种方法。Dispose方法应该释放所有的资源,同时也要调用其基类的Dispose方法释放其基类的 所有资源。基类的Dispose方法也要释放它所占用的所有资源,相应的调用它的基类Dispose 释放它的基类占用的资源。如此通过基类的层次结构传递下去。为了保证资源总是被合适的 清理,Dispose应该可以被调用多次且不抛出任何异常。阿重要对于C+ +的程序来讲,不需要关系这个主题。相应的,需要查看V
36、C+ +中析构函数和 Finalizer 的内容。在.NET Framework 2.0中,C+编译器支持确定(deterministic) 的资源处理实现。而不允许直接实现Dispose方法。Dispose方法应该调用GC.SuppressFinalize方法。如果对象当前在finalization 队列中,GC.SuppressFinalize会阻止它的Finalize方法被调用。记住Finalize的执 行有损性能。如果Dispose方法已经完成了对象清理工作,就没有必要再让GC去调用对 象的Finalize方法。1注意为System.GC.KeepAlive提供的例程表明了强制的垃圾回
37、收在一个回收对象的成员仍 然在执行时如何引起finalizer运行的。这是一个好的做法,在冗长的Dispose方法结尾 调用 KeepAlive方法。(?)下边的例程给出了对那些封装有非托管资源的类实现Dispose方法的推荐的设计模 式。资源类一般从复杂的基本类(complex native classes)或 API继承过来,相应的也必 须要要定制它。使用该代码模型作为创建一个资源类的开始,并基于你封装的资源进行必要 的定制。你不能编译下边的例程,也不能在应用程序中直接使用。在这个例子中,基类 BaseResource实现了一个公共的 Dispose方法。它调用 virtual Dispo
38、se(bool disposing)方法,参数的值依赖于调用者。在 virtual Dispose 方 法中合适的清理代码被执行。Dispose(bool disposing)执行两个不同的场景。如果参数disposing为true,该方 法被用户代码直接或间接的调用来处理托管和非托管的资源。如果参数disposing为false, 该方法在finalizer内部由运行库调用,仅仅非托管资源被处理。当一个对象正在执行 finalization代码时,它不应该引用其他的对象,因为finalizer不能以一个特定的顺序执 行。如果一个正在执行的finalizer引用了其他已经finalize的对象
39、,那将会失败。基类提供一个Finalize方法(或者析构函数)作为Dispose没有被调用的保护Finalize 方法传递false参数调用Dispose方法。类 MyResourceWrapper表明如何继承于一个实现 Dispose 的类。 MyResourceWrapper 重写 了 virtual Dispose(bool disposing)方 法。 MyResourceWrapper也调用其基类的Dispose以确保基类可以正确的进行清理。注意, 继承类MyResourceWrapper没有Finalize方法、没有参数的Dispose方法,因为它可 以从基类中继承它们。1注意方法
40、Dispose(bool disposing)不执行(enforce)线程安全性,因为该方法不能被一个用 户线程以及finalizer线程同时调用。另外,一个使用BaseResource的客户程序不能允 许多个用户线程同时调用这个方法。一个应用程序或类应该被设计成仅允许一个线程拥有 一个资源的生命周期且当资源不再使用时调用Dispose。依赖于这些资源,在资源处理时, 非同步线程的访问会有安全风险。开发者应该审查它们的代码以确定最好的执行线程安全的方法。C#/ Design pattern for the base class./ By implementing Disposable, you
41、 are announcing that instances / of this type allocate scarce resources.public class BaseResource: Disposable / Pointer to an external unmanaged resource. private IntPtr handle;/ Other managed resource this class uses. private Component Components;/ Track whether Dispose has been called. private boo
42、l disposed = false;/ Constructor for the BaseResource object. public BaseResource() / Insert appropriate constructor code here./ Implement Disposable./ Do not make this method virtual./ A derived class should not be able to override this method. public void Dispose() Dispose(true);/ Take yourself of
43、f the Finalization queue/ to prevent finalization code for this object / from executing a second time.GC.SuppressFinalize(this);/ Dispose(bool disposing) executes in two distinct scenarios./ If disposing equals true, the method has been called directly /or indirectly by a users code. Managed and unm
44、anaged resources / can be disposed./ If disposing equals false, the method has been called by the /runtime from inside the finalizer and you should not reference / other objects. Only unmanaged resources can be tected virtual void Dispose(bool disposing) / Check to see if Dispose has alr
45、eady been called. if(!this.disposed)/ If disposing equals true, dispose all managed / and unmanaged resources.if(disposing)/ Dispose managed resources.Components.Dispose();/ Release unmanaged resources. If disposing is false, / only the following code is executed. CloseHandle(handle);handle = IntPtr
46、.Zero;/ Note that this is not thread safe./ Another thread could start disposing the object/ after the managed resources are disposed,/ but before the disposed flag is set to true./ If thread safety is necessary, it must be/ implemented by the client.disposed = true;/ Use C# destructor syntax for fi
47、nalization code./ This destructor will run only if the Dispose method/ does not get called./ It gives your base class the opportunity to finalize./ Do not provide destructors in types derived from this class.BaseResource()/ Do not re-create Dispose clean-up code here./ Calling Dispose(false) is opti
48、mal in terms of/ readability and maintainability.Dispose(false);/ Allow your Dispose method to be called multiple times, / but throw an exception if the object has been disposed. / Whenever you do something with this class, / check to see if it has been disposed.public void DoSomething() if(this.dis
49、posed) throw new ObjectDisposedException();/ Design pattern for a derived class./ Note that this derived class inherently implements the/ IDisposable interface because it is implemented in the base class. public class MyResourceWrapper: BaseResource / A managed resource that you add in this derived
50、class. private ManagedResource addedManaged;/A native unmanaged resource that you add in this derived class. private NativeResource addedNative;private bool disposed = false;/ Constructor for this object. public MyResourceWrapper() / Insert appropriate constructor code here. protected override void
51、Dispose(bool disposing) if(!this.disposed) try if(disposing) / Release the managed resources you added in / this derived class here. addedManaged.Dispose();/ Release the native unmanaged resources you added / in this derived class here. CloseHandle(addedNative); this.disposed = true; finally / Call
52、Dispose on your base class. base.Dispose(disposing); / This derived class does not have a Finalize method/ or a Dispose method without parameters because it inherits / them from the base class.实现Close方法For types where calling a Close method is more natural than calling a Dispose method, add a public
53、 Close method to the base type. ThdClose method in turn calls theDispose method without parameters, which performs the proper cleanup operations. The following code example illustrates a Close method.C#/ Do not make this method virtual./ A derived class should not be allowed/ to override this method
54、.public void Close()/ Calls the Dispose method without parameters.Dispose();3.1如何清理托管资源在Dispose方法中,托管资源不需要被清理。对于实现了 IDisposable的托管对象,还是应该主动释放的,否则可能有泄漏的危险。应该总是避免直接调用GC.Collect HYPERLINK /MSDN/ShowPost.aspx?PostID=2542419&SiteID=1 /MSDN/ShowPost.aspx?PostID=2542419&SiteID=1C#public class UserProfile : IDisposableSystem.Drawing.Image _UserImage = null;public System.Drawing.Image Userimageget return _UserImage; set _UserImage = value; private string _UserName = string.Empty;public string UserName
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 口腔护士专业职业规划
- 儿科护理三年规划
- 小学生五项管理
- 特殊室护理质量检查
- 小儿口炎的临床特征
- 胎儿偏小的临床特征
- 《CAI课件制作》课件
- 《爱情向左我向右》课件
- 环保科技:创新绿色废弃物资源化利用技术
- 商品代理合作合同
- 2024年1月浙江首考英语试题和答案
- 70岁以上驾考三力测试题型
- 婚前债务协议
- 机械工程图识图基础知识培训
- 培养幼儿人际交往能力
- 2024年纳税服务条线专业知识考试题库(含答案)
- 沪科版九年级物理 第十七章 从指南针到磁浮列车 章末复习(课件)
- 2016-2023年北京交通职业技术学院高职单招(英语/数学/语文)笔试历年参考题库含答案解析
- 红色记忆-纪念一二九运动主题班会课件
- 畜禽粪污资源化利用项目规划设计方案
- 我的家乡南充
评论
0/150
提交评论