IntPtr,SafeHandle和HandleRef - 解释

use*_*572 39 .net winapi interop

在没有指向MSDN的情况下,有人可以简明扼要地解释每个问题的目的以及何时使用它们.(IntPtr,SafeHandle和HandleRef)

Mic*_*urr 51

IntPtr 只是一个简单的基于整数的结构,可以保存一个指针(即,32位系统上的32位大小,64位系统上的64位大小).

SafeHandle是一个用于保存Win32对象句柄的类 - 它有一个终结器,用于确保在对象为GC时关闭句柄. SafeHandle是一个抽象类,因为不同的Win32句柄有不同的方式需要关闭.在引入之前SafeHandle,IntPtr用于保存Win32句柄,但确保它们被正确关闭并防止被GC控制是程序员的责任.

HandleRef是一种在P/Invoke调用过程中确保非托管句柄不是GC的方法.如果没有类似的东西HandleRef,如果P后您的托管代码没有与处理任何事情/ Invoke调用,如果GC是在P期间运行/ Invoke调用它不会意识到句柄仍在使用,可能GC它.我想(但我不确定并且没有看过)SafeHandle可能会HandleRef用作其封装句柄管理的一部分.

  • 小修正.如果您不想在PInvoke期间使用*managed*对象GC,请使用HandleRef.例如,类HWnd {public IntPtr Handle; HWnd a = new HWnd(); B.SendMessage(a.Handle,......); < - a可以在PInvoke中进行GC.SendMessage(新的HandleRef(a,a.Handle))< - 现在不能在PInvoke中进行GC (14认同)
  • 另外一个补充:`SafeHandle`包括引用计数以防止句柄回收攻击. (4认同)
  • @Assimilater 是的:机制是相似的。HandleRef 和 SafeHandle 都受到 GC 保护,直到调用返回;并且都保护对象的终结器免于运行和删除 IntPtr。HandleRef _指向_具有该终结器的对象;而 SafeHandle _is_ 具有该终结器的对象。 (3认同)

小智 18

HWnd a = new HWnd();
B.SendMessage(a.Handle, ...);
Run Code Online (Sandbox Code Playgroud)

假设这是程序中对"a"的唯一引用,这相当于:

HWnd a = new HWnd();
IntPtr h = a.Handle;
// a is no longer needed and thus can be GC'ed
B.SendMessage(h, ...);
Run Code Online (Sandbox Code Playgroud)

问题是,当"a"被丢弃时,它将关闭手柄.如果在调用SendMessage之前或期间发生这种情况,则句柄将无效.

HandleRef防止"a"在程序完成之前被垃圾收集.