可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am getting this exception sometimes while running my Windows Forms app for a long time:
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)
What could be the cause for this?
回答1:
Just to sum it up, the custom grid I wrote, that is based on the .Net's DataGridView, uses custom code to draw cells. Rows in my grid can span multiple visual pages. (That was a business requirement)
The problem was that .Net pre-allocates a buffer of memory for controls with DoubleBuffering enabled. For DataGridViews grids the buffer needs to be rather large to accommodate possible large rows in the grid. In extreme cases a row can span up to 32000 pixels (because of a .net limitation). Grid widths in the project are usually between 500 and 800 pixels.
So the resulting buffer can be (32bpp * 800 * 32000 = ~100MB)
So in short, the system could not create compatible graphics objects, because occasionally, it could not reserve a buffer large enough to fit the required data.
To fix it I had to introduce a series of optimizations:
- limited max row height allowed in my custom grid to 1500 pixels
- updated buffer re-allocation code to only execute when the new buffer size is greater than the existing
- ensured that the buffers are not reallocated with every data binding, and preallocated to a sensible size.
- reviewed all code and made sure that unmanaged resources are properly disposed when not in use, as recommended here: http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
回答2:
Windows has a hard limit of 10000 handles per process. The rather unhelpful exception "The operation completed successfully" might indicate that this limit was reached.
If this happened because of a resource leak in your code, then you are in luck, as you at least have the opportunity to fix your code.
Unfortunately, there is scarcely little you can do about handles created internally by WinForms. For example, the prolific creation of font handles by TreeView control makes it hard to use in a scenario where very large tree needs to be represented in UI.
Some useful links:
http://support.microsoft.com/kb/327699
http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
回答3:
I once had a similar exception, when creating a huge PictureBox. It seems that I could not allocate a Graphics big enough. Actually, what I was doing was drawing some sort of map for a simple game, and I had a zoom in functionality, that basically created a bigger buffer and then I redrawed all the graphics in a bigger scale. Playing with this zoom in function for a long time or to a deep enough level caused this exception. Perhaps you are creating lots of Graphics and not dispossing them, or just a Graphic big enough to not be allocatable.
回答4:
I had the same problem in VB.NET.
The reason for this was weird:
In Austria, our Windows Systems usually have a , as comma and a . as thousands-seperator.
If this is twisted (which is standard in US I think) Windows will throw this Error.
Changing it as it should be in Austria solved the whole thing...
Good luck!
回答5:
Found this which may help - seems to be a Graphics or Control disposal issue
回答6:
Its caused in extreme cases by not disposing images. You should make use of IDisposable when loading bitmaps to overcome this;
using(Bitmap b = Bitmap.FromFile("myfile.jpg"))
{
//Do whatever
}
回答7:
Might also have something to do with memory fragmentation. We use an unmanaged component in out app as well, and there may be issues with not being able to allocate a large enough buffer for the double-buffered graphics, when the unmanaged component has eaten all the large contiguous blocks.
回答8:
Also, memory leaks can cause the exception to be thrown. For example, an application with 2-3 web browsers could reach over 1 GB in a few minutes, due to one of the internet explorer bugs like this.