C#资源释放方法实例分析

2019-12-26 18:07:38于丽

3.4.如果在对象被释放后调用其他方法,则可能会引发 ObjectDisposedException。

三、实例解析

1.下面代码对Dispose方法做了封装,说明如何在使用托管和本机资源的类中实现 Dispose(bool) 的常规示例:


public class BaseResource : IDisposable
{
  // 非托管资源
  private IntPtr _handle;
  //托管资源
  private Component _components;
  // Dispose是否被调用
  private bool _disposed = false;
  public BaseResource() { }
  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
  protected virtual void Dispose(bool disposing)
  {
    if (!this._disposed)
    {
      if (disposing)
      {
        // 释放托管资源
        _components.Dispose();
      }
      // 释放非托管资源,如果disposing为false, 只有非托管资源被释放
      CloseHandle(_handle);
      _handle = IntPtr.Zero;
      // 注意这里不是线程安全的
    }
    _disposed = true;
  }
  // 析构函数只会在我们没有直接调用Dispose方法的时候调用
  // 派生类中不用在次提供析构函数
  ~BaseResource() { Dispose(false); }
  // 如果你已经调用了Dispose方法后再调用其他方法会抛出ObjectDisposedException
  public void DoSomething()
  {
    if (this._disposed)
    {
      throw new ObjectDisposedException();
    }
  }
}
public class MyResourceWrapper : BaseResource
{
  // 托管资源
  private ManagedResource _addedManaged;
  // 非托管资源
  private NativeResource _addedNative;
  private bool _disposed = false;
  public MyResourceWrapper() { }
  protected override void Dispose(bool disposing)
  {
    if (!this._disposed)
    {
      try
      {
        if (disposing)
        {
          _addedManaged.Dispose();
        }
        CloseHandle(_addedNative);
        this._disposed = true;
      }
      finally
      {
        base.Dispose(disposing);
      }
    }
  }
}

2.使用CLR垃圾收集器,您不必再担心如何管理对托管堆分配的内存,不过您仍需清理其他类型的资源。托管类通过IDisposable接口使其使用方可以在垃圾收集器终结对象前释放可能很重要的资源。通过遵循disposable模式并且留意需注意的问题,类可以确保其所有资源得以正确清理,并且在直接通过Dispose调用或通过终结器线程运行清理代码时不会发生任何问题。

希望本文所述对大家C#程序设计有所帮助。



注:相关教程知识阅读请移步到c#教程频道。