c# - System.ComponentModel.Win32Exception: la operación se completó correctamente
.net winforms (8)
A veces obtengo esta excepción mientras ejecuto mi aplicación de Windows Forms durante mucho tiempo:
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)
¿Cuál podría ser la causa de esto?
Además, las pérdidas de memoria pueden provocar que se lance la excepción. Por ejemplo, una aplicación con 2-3 navegadores web podría alcanzar más de 1 GB en pocos minutos, debido a uno de los errores de Internet Explorer como this .
Encontré http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html que puede ayudar - parece ser un problema de eliminación de Gráficos o Control
Es causado en casos extremos por no disponer de imágenes. Debe utilizar IDisposable al cargar mapas de bits para superar esto;
using(Bitmap b = Bitmap.FromFile("myfile.jpg"))
{
//Do whatever
}
Para resumir, la cuadrícula personalizada que escribí, que se basa en DataGridView de .Net, usa un código personalizado para dibujar celdas. Las filas en mi cuadrícula pueden abarcar varias páginas visuales. (Eso era un requisito de negocio)
El problema fue que .Net asigna previamente un búfer de memoria para los controles con DoubleBuffering habilitado. Para las cuadrículas de DataGridViews, el búfer debe ser bastante grande para acomodar posibles filas grandes en la cuadrícula. En casos extremos, una fila puede abarcar hasta 32000 píxeles (debido a una limitación de .net). Los anchos de cuadrícula en el proyecto son generalmente entre 500 y 800 píxeles. Así que el búfer resultante puede ser (32bpp * 800 * 32000 = ~ 100MB)
Entonces, en resumen, el sistema no pudo crear objetos gráficos compatibles, porque ocasionalmente, no pudo reservar un búfer lo suficientemente grande para ajustarse a los datos necesarios.
Para solucionarlo tuve que introducir una serie de optimizaciones:
- Altura máxima de fila limitada permitida en mi cuadrícula personalizada a 1500 píxeles
- código de reasignación del búfer actualizado para que se ejecute solo cuando el nuevo tamaño del búfer sea mayor que el existente
- aseguró que los buffers no se reasignen con cada enlace de datos, y se preallocen a un tamaño razonable.
- revisó todo el código y se aseguró de que los recursos no administrados se eliminen correctamente cuando no están en uso, como se recomienda aquí: http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
También podría tener algo que ver con la fragmentación de la memoria. También utilizamos un componente no administrado en nuestra aplicación, y puede haber problemas con el hecho de no poder asignar un búfer suficientemente grande para los gráficos con doble búfer, cuando el componente no administrado ha consumido todos los bloques contiguos grandes.
Tuve el mismo problema en VB.NET. La razón de esto era rara:
En Austria, nuestros sistemas Windows suelen tener una, como coma y una. como miles-separador. Si esto está torcido (lo cual es estándar en los Estados Unidos, creo), Windows lanzará este error. Cambiándolo como debería estar en Austria resolvió todo ...
¡Buena suerte!
Una vez tuve una excepción similar, al crear un gran PictureBox. Parece que no pude asignar un gráfico lo suficientemente grande. En realidad, lo que estaba haciendo era dibujar una especie de mapa para un juego simple, y tenía una funcionalidad de zoom, que básicamente creó un búfer más grande y luego volví a dibujar todos los gráficos en una escala más grande. Jugar con esta función de zoom durante mucho tiempo o en un nivel suficientemente profundo causó esta excepción. Quizás esté creando muchos Gráficos y no los despoja, o simplemente un Gráfico lo suficientemente grande como para no ser asignable.
Windows tiene un límite de 10000 manejadores por proceso. La excepción bastante inútil "La operación se completó con éxito" podría indicar que se alcanzó este límite.
Si esto sucedió debido a una pérdida de recursos en su código, entonces está de suerte, ya que al menos tiene la oportunidad de corregir su código.
Desafortunadamente, no hay mucho que puedas hacer con los controladores creados internamente por WinForms. Por ejemplo, la prolífica creación de controladores de fuente por el control TreeView hace que sea difícil de usar en un escenario en el que se necesita representar un árbol muy grande en la interfaz de usuario.
Algunos enlaces útiles:
http://support.microsoft.com/kb/327699 http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html