例如,在旧的.NET Framework2.0源代码(Windows,VisualStudio2005-Whidbey)中,使用HandleRef定义了GetClientRect函数。
[DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)]
public static extern bool GetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); 在新的Windows代码包(来自微软,2009/2010)中,使用IntPtr定义了相同的函数
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetClientRect(IntPtr hwnd, ref CoreNativeMethods.RECT rect);实际上,HandleRef没有在任何Windows代码包源文件中使用,而在旧的.NET Framework源文件中的本机方法签名中大量使用它。
发布于 2010-12-02 16:04:30
有点可疑。当句柄值存储在HandleRef派生对象中时,不需要SafeHandle。代码包声明为ZeroInvalidHandle,其中包含几个派生的代码,如SafeWindowHandle。
但是,它实际上并没有在任何地方使用这些SafeHandle类。不太确定是否真的有必要,很多Vista和Win7扩展实际上都是COM接口。而不是传统的基于句柄的C API。它们通过引用计数保持存活,因此不受此类垃圾收集器故障的影响。
就我个人而言,我从不担心这件事。在API调用执行时收集类对象是一个错误。在API调用完成后,它可以很容易地发生--一微秒。仍然是一个bug,只是不是一个使API调用失败的错误。不太确定我是否真的希望它不会失败,我更喜欢在代码中出现bug时出现异常。微软需要保护自己不受这种情况的影响,他们不想因此而受到指责。我知道。
发布于 2010-12-02 13:26:12
我的猜测是,更新的代码示例使用IntPtr 仅仅是因为它更容易理解。
快速浏览一下Reflector,看看在NativeMethods框架中找到的各种.NET类中的函数签名,就会发现实际的用法在这两者之间是很好的分离。
我假设这是基于是否需要防止对象过早地被垃圾收集(这是使用主要优势的HandleRef)。还要记住,除非要传递的句柄是托管对象,否则使用HandleRef是不必要的。非托管对象将不会被垃圾回收。
发布于 2010-12-02 13:17:12
IntPtr只是封装指针的结构。至于 HandleRef MSDN 他说,“用HandleRef包装句柄保证在平台调用完成之前不会垃圾收集托管对象”。如果在P/Invoke调用之后不对句柄进行任何处理,GC就有可能在P/Invoke期间完成句柄。所以HandleRef看起来更安全。
https://stackoverflow.com/questions/4335261
复制相似问题