System.ComponentModel.Win32Exception:操作成功完成
我有时会在运行Windows Forms应用程序时遇到此exception:
System.ComponentModel.Win32Exception: The operation completed successfully at System.Drawing.BufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits) at System.Drawing.BufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height) at System.Drawing.BufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) at System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) at System.Drawing.BufferedGraphicsContext.Allocate(IntPtr targetDC, Rectangle targetRectangle) at System.Windows.Forms.Control.WmPaint(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.DataGridView.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
可能是什么原因造成的?
总结一下,我写的自定义网格,基于.Net的DataGridView,使用自定义代码绘制单元格。 我的网格中的行可以跨越多个可视页面。 (这是业务要求)
问题是.Net为启用了DoubleBuffering的控件预先分配了一个内存缓冲区。 对于DataGridViews网格,缓冲区需要相当大,以适应网格中可能存在的大行。 在极端情况下,行最多可以跨越32000像素(因为.net限制)。 项目中的网格宽度通常在500到800像素之间。 因此得到的缓冲区可以是(32bpp * 800 * 32000 = ~100MB)
简而言之,系统无法创建兼容的图形对象,因为偶尔它无法保留足够大的缓冲区以适应所需的数据。
为了解决这个问题,我不得不引入一系列优化:
- 我的自定义网格中允许的最大行高限制为1500像素
- 更新缓冲区重新分配代码仅在新缓冲区大小大于现有缓冲区时执行
- 确保缓冲区不会与每个数据绑定重新分配,并预先分配到合理的大小。
- 检查所有代码并确保在不使用时正确处理非托管资源,如下所示: http : //nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
Windows每个进程的硬限制为10000个句柄 。 相当无益的exception“操作成功完成”可能表示已达到此限制。
如果由于代码中的资源泄漏而发生这种情况,那么您很幸运,因为您至少有机会修复代码。
不幸的是,你几乎没有办法在WinForms内部创建的句柄上做。 例如,TreeView控件大量创建字体句柄使得在需要在UI中表示非常大的树的场景中很难使用它。
一些有用的链接:
http://support.microsoft.com/kb/327699 http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
在创建一个巨大的PictureBox时,我曾经遇到过类似的exception。 似乎我无法分配足够大的图形。 实际上,我正在做的是为一个简单的游戏绘制某种地图,我有一个放大function,基本上创建了一个更大的缓冲区,然后我重新绘制了更大规模的所有图形。 长时间使用此放大function或达到足够深的水平会导致此exception。 也许你正在创建大量的图形而不是处理它们,或者只是一个足够大的图形而不能分配。
我在VB.NET中遇到了同样的问题。 原因很奇怪:
在奥地利,我们的Windows系统通常有一个逗号和一个。 作为成千上万的分离者。 如果这是扭曲的(我认为这是美国的标准),Windows将抛出此错误。 改变它应该在奥地利解决了整个事情……
祝好运!
发现这可能有所帮助 – 似乎是图形或控制处理问题
它是在极端情况下通过不处理图像引起的。 加载位图时应该使用IDisposable来克服这个问题;
using(Bitmap b = Bitmap.FromFile("myfile.jpg")) { //Do whatever }
可能还与内存碎片有关。 我们在out app中也使用了非托管组件,当非托管组件吃掉所有大的连续块时,可能会出现无法为双缓冲图形分配足够大的缓冲区的问题。
此外,内存泄漏可能导致抛出exception。 例如,具有2-3个Web浏览器的应用程序可能会在几分钟内达到1 GB以上,这是由于此类 Internet Explorer之一的错误。