HandleRef 和 GCHandle 有什么区别?

发布于 2024-12-21 22:37:09 字数 465 浏览 3 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温折酒 2024-12-28 22:37:09

这两个结构的目的是防止垃圾收集器在 P/Invoke 调用完成之前释放资源并使句柄无效。您链接的文档表明这些是互操作编组器识别的特殊类型。

我从文档中了解到,HandleRef 本质上是更通用的 GCHandle 结构的特例。

HandleRef 结构专门用于包装与 P/Invoke 代码一起使用的非托管资源的句柄。例如,窗口句柄 (HWND) 或设备上下文 (HDC)。它有一个 Handle 属性,该属性返回一个 IntPtr 类型的值,该值是底层系统体系结构上指针大小的整数值。您可以使用它来快速&轻松获得它包裹的手柄。

尽管 GCHandle 结构允许使用 GCHandleType 枚举的成员之一指定它所包装的句柄类型,但 HandleRef 结构是专门为旨在包装非托管资源的句柄。当您直接处理非托管内存时,您可能会使用 GCHandle 结构,而不是 Win32 API 视为黑匣子的特殊句柄。

两者都没有必要使用。我们可以简单地调用 GC.KeepAlive 来防止垃圾收集器过早释放资源。

即使这样也可能没有必要。我多年来一直在编写 P/Invoke 代码,并且发现如果编写正确,就不需要这两种结构。如果在 API 调用执行过程中类对象被垃圾回收,那么这就是应用程序中的错误。我实际上希望通过异常收到失败通知,而不是隐藏它。

The point of both these structures is to prevent the garbage collector from releasing a resource and invalidating the handle before the P/Invoke call has finished. The documentation you linked indicates that these are special types recognized by the interop marshaller.

What I gather from the documentation is that HandleRef is essentially a special case of the more general GCHandle structure.

The HandleRef structure is specifically intended for wrapping handles to unmanaged resources that are used with P/Invoke code. For example, window handles (HWND) or device contexts (HDC). It has a Handle property that returns a value of type IntPtr, which is an integer value the size of a pointer on the underlying system's architecture. You can use this to quickly & easily obtain the handle it wraps.

Whereas the GCHandle structure allows one to specify the type of handle it wraps using one of the members of the GCHandleType enumeration, the HandleRef structure was specifically designed to wrap handles to unmanaged resources. You'd probably use the GCHandle structure when you're dealing directly with unmanaged memory, rather than the special handles that the Win32 API treats as black boxes.

It is not necessary to use either. One can simply call GC.KeepAlive to keep the garbage collector from prematurely releasing the resource.

And even that is probably not necessary. I've been writing P/Invoke code for years, and I've found that when it's correctly written, there's no need for either of these structures. If a class object gets garbage collected while the API call is in the middle of executing, then that's a bug in your application. I actually want to be notified of the failure via an exception, not hide it.

相思故 2024-12-28 22:37:09

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

HandleRef 值类型与 GCHandle 一样,是一种可识别的特殊类型
由互操作封送拆收器。正常的、非固定的 GCHandle 也会阻止
不及时的垃圾收集,但 HandleRef 提供了更好的
表现。尽管使用 HandleRef 来保持对象存活
平台调用的持续时间是首选,您也可以使用
GC.KeepAlive 方法用于相同目的。

One difference is given in the link you mentioned:

The HandleRef value type, like GCHandle, is a special type recognized
by the interop marshaler. A normal, nonpinned GCHandle also prevents
untimely garbage collection, yet HandleRef provides better
performance. Although using HandleRef to keep an object alive for the
duration of a platform invoke call is preferred, you can also use the
GC.KeepAlive method for the same purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文