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之一的错误。