我试图使用System.Runtime.InteropServices.SafeHandle的子类来管理指向Win32 GUI对象(即HWND和HMENU)的指针。然后,我将使用这些句柄在C#中实现一个基于Win32 32的GUI库。在此过程中,我创建一个菜单并将其分配给一个窗口。但是,假设我没有保留包含SafeHandle的HMENU,以便在拥有它的窗口之前收集垃圾。当所有HMENU指针的SafeHandles消失时,我不能简单地销毁它们,因为这样的事情就会发生:
HMENU,并将它分配给一个自动调用DestroyMenu()的SafeHandle子类。HWND,并使用SetMenu() Win32 API调用为它分配HMENU。HWND现在保留了HMENU,所以它不应该被销毁(通过DestroyMenu()),直到拥有它的HWND被销毁为止。HMENU封装在一个SafeHandle中,GC很快就会释放SafeHandle,从而销毁HMENU,而它仍然被HWND引用。我能做些什么来确保HMENU在需要的时候一直存在,但是一旦拥有的HWND是GCed,它仍然会被销毁吗?我看了一下this question,它几乎是理想的,只是它谈到了使用具有内建引用计数的本地库。Win32不存在-一个句柄要么存在,要么被销毁。我考虑使用像SafeHandle这样的类来添加我自己的引用计数,但是由于程序中引用HMENU的所有部分(即Win32)都不能访问我的引用计数类,所以受到了阻碍。这与我的用例有关吗?还有其他方法可以/应该实现这样的API包装器吗?
发布于 2015-07-29 05:06:12
简单的回答是,在不再需要Win32之前,无法使HMENU保持对.net对象的引用。
您可以做的是用您自己的类包装HWND,并在您的SetMenu上在对象中保存一个引用--但是这是行不通的,因为:
这在参考计数本地框架中有效,因为与GC不同,发布引用是100%可预测和可控的。
(基本上,WinForms的设计方式是有原因的)
https://stackoverflow.com/questions/31691183
复制相似问题