首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SafeHandle用于包装非拥有的指针。

SafeHandle用于包装非拥有的指针。
EN

Stack Overflow用户
提问于 2015-07-29 04:23:11
回答 1查看 194关注 0票数 0

我试图使用System.Runtime.InteropServices.SafeHandle的子类来管理指向Win32 GUI对象(即HWNDHMENU)的指针。然后,我将使用这些句柄在C#中实现一个基于Win32 32的GUI库。在此过程中,我创建一个菜单并将其分配给一个窗口。但是,假设我没有保留包含SafeHandle的HMENU,以便在拥有它的窗口之前收集垃圾。当所有HMENU指针的SafeHandles消失时,我不能简单地销毁它们,因为这样的事情就会发生:

  1. 我创建一个HMENU,并将它分配给一个自动调用DestroyMenu()SafeHandle子类。
  2. 我创建了一个顶级HWND,并使用SetMenu() Win32 API调用为它分配HMENU
  3. 因为HWND现在保留了HMENU,所以它不应该被销毁(通过DestroyMenu()),直到拥有它的HWND被销毁为止。
  4. 但是,由于我将HMENU封装在一个SafeHandle中,GC很快就会释放SafeHandle,从而销毁HMENU,而它仍然被HWND引用。
  5. 我的程序会因为使用显式删除的句柄而崩溃。

我能做些什么来确保HMENU在需要的时候一直存在,但是一旦拥有的HWND是GCed,它仍然会被销毁吗?我看了一下this question,它几乎是理想的,只是它谈到了使用具有内建引用计数的本地库。Win32不存在-一个句柄要么存在,要么被销毁。我考虑使用像SafeHandle这样的类来添加我自己的引用计数,但是由于程序中引用HMENU的所有部分(即Win32)都不能访问我的引用计数类,所以受到了阻碍。这与我的用例有关吗?还有其他方法可以/应该实现这样的API包装器吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-29 05:06:12

简单的回答是,在不再需要Win32之前,无法使HMENU保持对.net对象的引用。

您可以做的是用您自己的类包装HWND,并在您的SetMenu上在对象中保存一个引用--但是这是行不通的,因为:

  1. 不允许从终结器中销毁GDI对象,因为终结器是从GC中的专用线程调用的,并且只允许从创建GDI对象的线程中触摸GDI对象(大部分时间它将对工作进行排序,但您正在以不受支持的方式使用API )。
  2. 从终结器中释放一个HWND (即使允许)将使窗口在完全不可预测的时候从屏幕上消失。

这在参考计数本地框架中有效,因为与GC不同,发布引用是100%可预测和可控的。

(基本上,WinForms的设计方式是有原因的)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31691183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档