我们已经知道了处置那些占用非受控(unmanaged)资源的对象的重要性,现在应该编写资源管理代码来处置那些包含非内存资源的类型了。整个.net框架组件都使用一个标准的模式来处理非内存资源。使用你建立的类型的用户也希望你遵循这个标准的模式。 标准的处理模式的思想是这样的:当客户端记得的时候使用idisposable接口释放你的非受控资源,当客户端忘记的时候防护性地使用终结器(finalizer)。它与垃圾收集器(garbage collector)一起工作,确保只在必要的时候该对象才受到与终结器相关的性能影响。这是处理非受控资源的一条很好的途径,因此我们应该彻底地认识它。
类层次体系中的根基类(root base class)必须实现idisposable接口以释放资源。这个类型还必须添加一个作为防御机制的终结器。所有这些程序都把释放资源的工作委托给一个虚拟的方法,衍生的类可以根据自己的资源管理需求来重载该方法。只要衍生的类必须释放自己的资源,并且它必须调用该函数的基类版本的时候,它才需要重载这个虚拟方法。
开始的时候,如果你的类使用了非内存资源,它就必须含有一个终结器。你不能依赖客户端总是调用dispose()方法。因为当它们忘记这样做的时候,你就面临资源泄漏的问题。没有调用dispose是它们的问题,但是你却有过失。用于保证非内存资源被正确地释放的唯一途径是建立终结器。
当垃圾收集器运行的时候,它立即从内存中删除所有不带终结器的垃圾对象。所有带有终结器的对象仍然存在于内存中。这些对象都被添加到终结队列,垃圾收集器引发一个新线程,周期性地在这些对象上运行终结器。在这些终结程序线程完成自己的工作之后,就可以从内存中删除垃圾对象了。需要终结的对象在内存中停留的时间比没有终结器的对象停留的时间长很多。但是你别无选择。如果要使程序有防护性,在类型包含非受控资源的时候,你必须编写一个终结器。但是也不用担心性能问题。下一步确保了客户端避免与终结相关的性能开销。
实现idisposable接口是一种标准的途径,它通知用户和运行时系统持有资源的对象必须及时地释放。idisposable接口仅仅包含一个方法:
| public interface idisposable { void dispose( ); } |
| protected virtual void dispose( bool isdisposing ); |
这个重载的方法实现支持finalize和dispose的必要事务,由于它是虚拟的,它为所有的衍生类提供了一个入口点。衍生类可以重载这个方法,为清除自己的资源提供适当的实现,同时还可以调用基类版本。当isdisposing为真(true)的时候,你可以清除受控和非受控资源,当isdisposing为假(false)的时候,你只能清除非受控资源。在这两种情况下,你都可以调用基类的dispose(bool)方法,让它清除自己的资源。
下面有一个简短的例子,它演示了你在实现这种模式的时候所提供的代码框架。myresourcehog类演示了实现idisposable接口、终结器的代码,并建立了一个虚拟的dispose方法:
| public class myresourcehog : idisposable { // 已经被处理过的标记 private bool _alreadydisposed = false; // 终结器。调用虚拟的dispose方法 ~myresourcehog() { dispose( false ); } // idisposable的实现 // 调用虚拟的dispose方法。禁止finalization(终结操作) public void dispose() { dispose( true ); gc.suppressfinalize( true ); } // 虚拟的dispose方法 protected virtual void dispose( bool isdisposing ) { // 不要多次处理 if ( _alreadydisposed ) return; if ( isdisposing ) { // todo: 此处释放受控资源 } // todo: 此处释放非受控资源。设置被处理过标记 _alreadydisposed = true; } } |
| public class derivedresourcehog : myresourcehog { // 它有自己的被处理过标记 private bool _disposed = false; protected override void dispose( bool isdisposing ) { // 不要多次处理 if ( _disposed ) return; if ( isdisposing ) { // todo: 此处释放受控资源 } // todo: 此处释放所有受控资源 // 让基类释放自己的资源。基类负责调用gc.suppressfinalize( ) base.dispose( isdisposing ); // 设置衍生类的被处理过标记 _disposed = true; } } |
| public class badclass { // 保存某个全局对象的引用 private readonly arraylist _finalizedlist; private string _msg; public badclass( arraylist badlist, string msg ) { // 缓冲该引用 _finalizedlist = badlist; _msg = (string)msg.clone(); } ~badclass() { // 把该对象添加到列表中。这个对象是可到达的,不再是垃圾了。它回来了! _finalizedlist.add( this ); } } |
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器