2个回答

8
这两种结构的目的都是为了防止垃圾回收器在P/Invoke调用完成之前释放资源并使句柄无效。您提供的文档表明这些是Interop marshaller识别的特殊类型。
从文档中我了解到,HandleRef实际上是更一般的GCHandle结构的一个特例。
HandleRef结构专门用于包装与P/Invoke代码一起使用的非托管资源的句柄,例如窗口句柄(HWND)或设备上下文(HDC)。它具有一个Handle属性,该属性返回IntPtr类型的值,这是底层系统体系结构上指针大小的整数值。您可以使用此属性快速轻松地获取其包装的句柄。
而GCHandle结构允许使用GCHandleType枚举的成员之一指定其包装的句柄类型,HandleRef结构是专门设计用于包装对非托管资源的句柄。当您直接处理非托管内存而不是Win32 API视为黑匣子的特殊句柄时,可能会使用GCHandle结构。
没有必要使用任何一种结构。您只需调用GC.KeepAlive即可防止垃圾回收器过早地释放资源。
甚至那也可能不是必要的。我已经写了多年的P/Invoke代码,并且发现当它正确编写时,不需要使用这两种结构。如果在API调用正在执行的过程中类对象被垃圾回收,则这是应用程序中的错误。实际上,我希望通过异常通知我失败,而不是隐藏它。

1
我发现当代码正确编写时,这两种结构都是不必要的。但如果您不担心对象被收集,因为您知道托管代码将保持对其的引用,但您仍希望非托管代码出于某种原因接受/保留/返回托管引用,该怎么办呢?例如用例:https://dev59.com/KI7da4cB1Zd3GeqP-0RC - jbatez

0

你提到的链接中给出了一个区别:

HandleRef值类型,像GCHandle一样,是Interop Marshaler识别的特殊类型。普通的非固定GCHandle也可以防止过早的垃圾回收,但HandleRef提供更好的性能。虽然在平台调用期间使用HandleRef来保持对象的存活是首选,但您也可以使用GC.KeepAlive方法来实现相同的目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接