龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

深入了解C#系列:谈谈C#中垃圾回收与内存管理机制(5)

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
public class BaseResource: IDisposable { // 指向外部非托管资源 private IntPtr handle; // 此类使用的其它托管资源. private Component Components; // 跟踪是否调用.Dispose方法,标

public class BaseResource: IDisposable
{
   // 指向外部非托管资源
   private IntPtr handle;
   // 此类使用的其它托管资源.
   private Component Components;
   // 跟踪是否调用.Dispose方法,标识位,控制垃圾收集器的行为
   private bool disposed = false;

   // 构造函数
   public BaseResource()
   {
      // Insert appropriate constructor code here.
   }

   // 实现接口IDisposable.
   // 不能声明为虚方法virtual.
   // 子类不能重写这个方法.
   public void Dispose()
   {
      Dispose(true);
      // 离开终结队列Finalization queue
      // 设置对象的阻止终结器代码
      //
      GC.SuppressFinalize(this);
   }

   // Dispose(bool disposing) 执行分两种不同的情况.
   // 如果disposing 等于 true, 方法已经被调用
   // 或者间接被用户代码调用. 托管和非托管的代码都能被释放
   // 如果disposing 等于false, 方法已经被终结器 finalizer 从内部调用过,
   //你就不能在引用其他对象,只有非托管资源可以被释放。
   protected virtual void Dispose(bool disposing)
   {
      // 检查Dispose 是否被调用过.
      if(!this.disposed)
      {
         // 如果等于true, 释放所有托管和非托管资源
         if(disposing)
         {
            // 释放托管资源.
            Components.Dispose();
         }
         // 释放非托管资源,如果disposing为 false,
         // 只会执行下面的代码.
         CloseHandle(handle);
         handle = IntPtr.Zero;
         // 注意这里是非线程安全的.
         // 在托管资源释放以后可以启动其它线程销毁对象,
         // 但是在disposed标记设置为true前
         // 如果线程安全是必须的,客户端必须实现。

      }
      disposed = true;        
   }
        // 使用interop 调用方法
        // 清除非托管资源.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

   // 使用C# 析构函数来实现终结器代码
   // 这个只在Dispose方法没被调用的前提下,才能调用执行。
   // 如果你给基类终结的机会.
   // 不要给子类提供析构函数.
   ~BaseResource()     
   {
      // 不要重复创建清理的代码.
      // 基于可靠性和可维护性考虑,调用Dispose(false) 是最佳的方式
      Dispose(false);
   }

   // 允许你多次调用Dispose方法,
   // 但是会抛出异常如果对象已经释放。
   // 不论你什么时间处理对象都会核查对象的是否释放,
   // check to see if it has been disposed.
   public void DoSomething()
   {
      if(this.disposed)
      {
         throw new ObjectDisposedException();
      }
   }
   对于需要调用Close方法比Dispose方法更加自然的类型,可以在  基类增加一个Close方法。
  Close方法无参调用执行恰当清理工作的Dispose方法。
  下面的例子演示了Close方法。
   // 不要设置方法为virtual.
   // 继承类不允许重写这个方法
   public void Close()
   {
   // 无参数调用Dispose参数.
       Dispose();
   }

   public static void Main()
   {
        // Insert code here to create
        // and use a BaseResource object.
   }
}
   总结:看了本文以后,不知对你是否有所帮助,如果你理解了.net垃圾回收的机制和GC的工作原理,以及包含如何管理非托管资源,你就会成为一个内存管理的高手。如果面试官问道这个问题,你就可以详细阐述你对这类问题的理解和看法。希望这篇文章能对你的工作和学习带来帮助~

DemoCodes/Files/frank_xl/MemoryManagement2008.zip

【作者】Frank Xu Lei

【地址】 http://www.cnblogs.com/frank_xl/archive/2009/02/19/1393566.html


精彩图集

赞助商链接