在没有指向MSDN的情况下,有人可以简明扼要地解释每个问题的目的以及何时使用它们。 (IntPtr,SafeHandle和HandleRef)
答案 0 :(得分:49)
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
作为其封装句柄管理的一部分。
答案 1 :(得分:17)
HWnd a = new HWnd();
B.SendMessage(a.Handle, ...);
假设这是程序中对“a”的唯一引用,这相当于:
HWnd a = new HWnd();
IntPtr h = a.Handle;
// a is no longer needed and thus can be GC'ed
B.SendMessage(h, ...);
问题是当处理“a”时,它会关闭手柄。如果在调用SendMessage之前或期间发生这种情况,则句柄将无效。
HandleRef防止“a”在程序完成之前被垃圾收集。
答案 2 :(得分:1)
看起来SafeHandle确实包含了HandleRef的KeepAlive行为: Project Roslyn SafeHandle.cs http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safehandle.cs,743afbddafaea263
/*
Problems addressed by the SafeHandle class:
1) Critical finalization - ensure we never leak OS resources in SQL. Done
without running truly arbitrary & unbounded amounts of managed code.
2) Reduced graph promotion - during finalization, keep object graph small
3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread ---- (HandleRef)
<...>
*/
但我不确定,看起来keepalive行为只能通过向构造函数提供false值来实现,构造函数只是将对象标记为无法终止,因此你必须手动调用SafeHandle的Dispose()来防止资源泄漏。我不对吗? 有人可以解释源代码,
是什么private extern void InternalDispose();
private extern void InternalFinalize();