System.ComponentModel.Win32Exception:操作成功完成

时间:2009-07-30 22:32:38

标签: c# .net winforms win32exception

我在运行Windows Forms应用程序很长一段时间时遇到此异常:

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)

原因可能是什么?

8 个答案:

答案 0 :(得分:21)

总而言之,我编写的自定义网格基于.Net的DataGridView,使用自定义代码绘制单元格。我的网格中的行可以跨越多个可视页面。 (这是业务要求)

问题在于.Net为启用了DoubleBuffering的控件预先分配了一个内存缓冲区。对于DataGridViews网格,缓冲区需要相当大,以适应网格中可能存在的大行。在极端情况下,行最多可以跨越32000像素(因为.net限制)。项目中的网格宽度通常在500到800像素之间。 因此得到的缓冲区可以是(32bpp * 800 * 32000 = ~100MB)

简而言之,系统无法创建兼容的图形对象,因为偶尔它无法保留足够大的缓冲区以适应所需的数据。

要修复它,我必须引入一系列优化:

  • 我的自定义网格中允许的最大行高限制为1500像素
  • 更新缓冲区重新分配代码,仅在新缓冲区大小大于现有
  • 时执行
  • 确保缓冲区不会与每个数据绑定重新分配,并预先分配到合理的大小。
  • 审核了所有代码,并确保在不使用时妥善处置非托管资源,如下所示:http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html

答案 1 :(得分:13)

Windows每个进程的硬性限制为 10000个句柄。相当无用的异常“操作成功完成”可能表示已达到此限制。

如果由于您的代码中的资源泄漏而发生这种情况,那么您很幸运,因为您至少有机会修复您的代码。

不幸的是,你几乎没有办法在WinForms内部创建的句柄上做。例如,TreeView控件大量创建字体句柄使得在需要在UI中表示非常大的树的场景中很难使用它。

一些有用的链接:

http://support.microsoft.com/kb/327699 http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html

答案 2 :(得分:3)

在创建一个巨大的PictureBox时,我曾遇到类似的异常。似乎我无法分配足够大的图形。实际上,我正在做的是为一个简单的游戏绘制某种地图,我有一个放大功能,基本上创建了一个更大的缓冲区,然后我重新绘制了更大规模的所有图形。长时间使用此放大功能或达到足够深的水平会导致此异常。也许你正在创建大量的图形而不是处理它们,或者只是一个足以不能分配的图形。

答案 3 :(得分:3)

我在VB.NET中遇到了同样的问题。 原因很奇怪:

在奥地利,我们的Windows系统通常有一个逗号和一个。作为成千上万的分离者。 如果这是扭曲的(我认为这是美国的标准),Windows将抛出此错误。 改变它应该在奥地利解决了整个问题......

祝你好运!

答案 4 :(得分:2)

找到可能有帮助的this - 似乎是图形或控件处理问题

答案 5 :(得分:2)

在极端情况下由于不处理图像而导致。加载位图时应该使用IDisposable来克服这个问题;

using(Bitmap b = Bitmap.FromFile("myfile.jpg"))
{
   //Do whatever
}

答案 6 :(得分:1)

也可能与内存碎片有关。我们在out app中也使用了非托管组件,当非托管组件吃掉所有大的连续块时,可能会出现无法为双缓冲图形分配足够大缓冲区的问题。

答案 7 :(得分:0)

此外,内存泄漏可能导致抛出异常。例如,由于某个Internet浏览器错误(如this),具有2-3个Web浏览器的应用程序可能会在几分钟内达到1 GB以上。