C# 调用Bitmap.GetHicon时GDI+中发生一般错误

C# 调用Bitmap.GetHicon时GDI+中发生一般错误,c#,gdi+,C#,Gdi+,为什么在GDI+异常中出现一般错误 IntPtr hicon = tempBitmap.GetHicon(); Icon bitmapIcon = Icon.FromHandle(hicon); return bitmapIcon; 应用程序运行超过30分钟时发生错误。我正在每秒将System.Drawing.Bitmap转换为System.Drawing.Icon 那是因为把手漏了。您可以使用TaskMgr.exe的“进程”选项卡诊断泄漏。查

为什么在GDI+异常中出现一般错误

IntPtr hicon = tempBitmap.GetHicon();             
Icon bitmapIcon = Icon.FromHandle(hicon);            
return bitmapIcon;
应用程序运行超过30分钟时发生错误。我正在每秒将System.Drawing.Bitmap转换为System.Drawing.Icon


那是因为把手漏了。您可以使用TaskMgr.exe的“进程”选项卡诊断泄漏。查看+选择列和勾选手柄、GDI对象和用户对象。在程序运行时观察这些列。如果我的猜测是正确的,您将看到进程的GDI对象值稳步上升。当它达到10000,那么表演就结束了,Windows拒绝让你泄漏更多的物体

Icon.FromHandle的备注部分显示:

使用此方法时,必须使用Win32 API中的DestroyIcon方法处理生成的图标,以确保释放资源


这是一个很好的建议,但通常做起来很痛苦。您可以找到一个黑客来强制图标对象拥有句柄,并在中自动释放它。相关代码位于调用专用图标构造函数部分之后。

您可能需要清理图标

MSDN上的示例演示了如何使用。不幸的是,它需要PInvoke:

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet=CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
然后在您的方法中:

IntPtr hicon = tempBitmap.GetHicon();             
Icon bitmapIcon = Icon.FromHandle(hicon);        

// And then somewhere later...
DestroyIcon(bitMapIcon.Handle);    

如果在使用DestryIcon之前调用它,它可能无法工作。就我自己的这个问题来说,我最后保留了对我创建的最后一个图标的引用,然后在下次生成图标时在其上调用DestroyIcon。

我需要每秒将System.Drawing.Bitmap转换为System.Drawing.icon为什么?gdi句柄的数量有限-你确定在某个时候处理/释放以前的gdi对象吗?@walther:Animated Tray偶像我有一个位图中的图形,我想把位图放到托盘图标中,我唯一的选择就是把它转换成图标。@Mike:我甚至不确定!我呼叫。使用图标后处理。我还要做什么?tmpIcon.Dispose这还不够吗?不,它没有把手。这就是为什么我建议黑客强迫它拥有手柄。在任务管理器中,句柄数是361,降到358,现在是357;2分钟后:345!!这似乎没有那么痛苦:按照添加3行似乎解决了我的问题。在Windows 10中,您仍然启动任务管理器,但随后转到“详细信息”选项卡,右键单击列标题以选择“选择列”。在这一点上,您可以添加句柄、GDI对象和用户对象?为了使MSDN示例中的语句“因为表单创建了自己的图标副本”为真,因为如果未加载窗口,则将在首次加载时进行复制,如果在此之前调用DestroyIcon,则当表单尝试从图标加载句柄时,将引发ObjectDisposedException。我想这就是您需要保留图标副本的原因。