zoukankan      html  css  js  c++  java
  • SafeHandle和Dispose z

    SafeHandle最大的意义是封装一个托管资源且本身会执行.NET中的资源释放模式(所谓的Dispose Pattern),这样,开发者在使用非托管资源时,不可以不需要执行繁琐的资源释放模式,而直接使用SafeHandle就可以了,另外SafeHandle继承自CriticalFinalizerObject类型,CLR对其的Finalize方法有特殊优化。

    整个.NET Framework内有许多SafeHandle,比如.NET 4新加的SafeBuffer(在System.Runtime.InteropServices命名空间内),使用它可以申请非托管内存资源。这样的话就不需要直接使用Marshal.AllocHGlobal和FreeHGlobal方法了。

    举一个简单的例子,使用GDI中的CreateSolidBrush返回一个非托管资源Handle,如果需要在类型中使用这个Handle,则要注意正确的资源释放,如下代码:

    //+ using System.Runtime.InteropServices; //使用GDI中CreateSolidBrush中的资源 publicclassMyPen : IDisposable { bool _isDisposed; IntPtr _gdiBrush;
    public MyPen() { _gdiBrush = CreateSolidBrush(0); }
    publicvoid Dispose() { Dispose(true); //不需要析构函数再次运行了 GC.SuppressFinalize(this); }
    //析构函数 ~MyPen() { Dispose(false); }
    //protected Dispose,被公共Dispose和析构函数调用 protectedvirtualvoid Dispose(bool disposing) { if(_isDisposed) { return; } if (disposing) { //释放托管资源 } //释放非托管资源 if (_gdiBrush !=IntPtr.Zero) { DeleteObject(_gdiBrush); _gdiBrush =IntPtr.Zero; } _isDisposed =true; }
    #region Win32 API [DllImport("gdi32.dll")] staticexternIntPtr CreateSolidBrush(uint crColor);
    [DllImport("gdi32.dll", EntryPoint ="DeleteObject")] staticexternbool DeleteObject([In] IntPtr hObject);
    #endregion }

    而如果用SafeHandle类型定义的话,使用起非托管资源就方便多了。

    首先,创建一个类型继承自Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid,改写ReleaseHandle方法来释放非托管资源。如下代码:

    //+ using Microsoft.Win32.SafeHandles; //+ using System.Runtime.InteropServices; classSafeBrushHandle : SafeHandleZeroOrMinusOneIsInvalid { public SafeBrushHandle(IntPtr handle)         : base(true)     { base.SetHandle(handle);     }
    protectedoverridebool ReleaseHandle() { //判断Handle合法 if (!this.IsInvalid) { //释放资源 return DeleteObject(this.handle); } returntrue; }
    [DllImport("gdi32.dll", EntryPoint ="DeleteObject")] staticexternbool DeleteObject([In] IntPtr hObject); }

    然后使用这个SafeHandle,我们的MyPen类型的执行就简单多了:

    //+ using System.Runtime.InteropServices; //使用SafeBrushHandle publicclassMyPen : IDisposable { bool _isDisposed; SafeBrushHandle _gdiBrush;
    public MyPen() { _gdiBrush =newSafeBrushHandle(CreateSolidBrush(0)); }
    publicvoid Dispose() { if (_isDisposed) { return; } _gdiBrush.Dispose(); _isDisposed =true; }
    #region Win32 API [DllImport("gdi32.dll")] staticexternIntPtr CreateSolidBrush(uint crColor);
    #endregion }

    所以,使用SafeHandle可以让使用非托管资源类型的定义更加简洁,因为不需要再定义析构函数了。非托管资源被SafeHandle包装好后,整个资源对象会表现起来像一个托管的对象(注意是表现起来像,本质上显然不是),即便是忘了调用它的Dispose方法,非托管资源也会随着SafeHandle被垃圾回收时而释放,因为SafeHandle的析构函数(Finalize方法)会调用内部的ReleaseObject方法的。

  • 相关阅读:
    BZOJ 1391: [Ceoi2008]order
    BZOJ 4504: K个串
    2019 年百度之星·程序设计大赛
    POJ 2398 Toy Storage (二分 叉积)
    POJ 2318 TOYS (二分 叉积)
    HDU 6697 Closest Pair of Segments (计算几何 暴力)
    HDU 6695 Welcome Party (贪心)
    HDU 6693 Valentine's Day (概率)
    HDU 6590 Code (判断凸包相交)
    POJ 3805 Separate Points (判断凸包相交)
  • 原文地址:https://www.cnblogs.com/zeroone/p/3708112.html
Copyright © 2011-2022 走看看