2009-07-30 27 views
21

estoy recibiendo esta excepción veces mientras se ejecuta mi aplicación Windows Forms desde hace mucho tiempo:System.ComponentModel.Win32Exception: La operación se ha completado con éxito

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?

+5

Encontré 1400 visitas en google sobre esto, pero nada que parece una explicación real. – Niki

Respuesta

19

Sólo para resumir, la cuadrícula personalizada que escribí, que se basa en DataGridView del .Net, utiliza código personalizado para extraer las células. Las filas en mi cuadrícula pueden abarcar múltiples páginas visuales. (Eso era un requisito empresarial)

El problema era que .Net preasigna un búfer de memoria para los controles con DoubleBuffering activado. Para las cuadrículas de DataGridViews, el almacenamiento intermedio 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 generalmente tienen entre 500 y 800 píxeles. Así que el búfer resultante puede ser (32bpp * 800 * 32000 = ~ 100MB)

En resumen, el sistema no pudo crear objetos gráficos compatibles, porque de vez en cuando, no podía reservar un búfer lo suficientemente grande para ajustarse a los datos requeridos .

Para solucionarlo tuve que introducir una serie de optimizaciones:

  • limitada altura de la fila máximo permitido en mi rejilla personalizada a 1500 píxeles
  • código
  • intermedia actualizada reasignación sólo a ejecutar cuando el nuevo buffer el tamaño es mayor que el existente
  • aseguró que los almacenamientos intermedios no se reasignan con cada enlace de datos y se asignan previamente a un tamaño razonable.
  • revisado todo el código y se aseguró de que los recursos no administrados se disponen adecuadamente cuando no esté en uso, como se recomienda aquí: http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
+18

Good Guy Greg en stackoverflow: resuelve su propio problema, POSTS SOLUTION. – matao

+1

Buen análisis, pero me gustaría ver un fragmento de código y más explicaciones sobre "series de optimizaciones". – ra170

+0

Buen punto, ra170, edité la pregunta y enumeré los pasos que se describieron anteriormente como "serie de optimizaciones". ¡Gracias! –

2

encontrado this que puede ayudar - Parece que hay una gráfica de control o eliminación tema

1

también podría tener algo que ver con la fragmentación de memoria. También utilizamos un componente no administrado en la aplicación de salida, y puede haber problemas con la imposibilidad de asignar un búfer lo suficientemente grande para los gráficos de doble búfer, cuando el componente no administrado se ha comido todos los bloques contiguos grandes.

2

Su causa en casos extremos es no tirar las imágenes. Debería utilizar IDisposable al cargar mapas de bits para superar esto;

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

Windows tiene un límite duro de 10000 maneja por proceso. La excepción bastante inútil "La operación se completó correctamente" podría indicar que se alcanzó este límite.

Si esto sucedió debido a una pérdida de recursos en su código, entonces tiene suerte, ya que al menos tiene la oportunidad de corregir su código.

Desafortunadamente, hay muy poco que pueda hacer sobre los identificadores creados internamente por WinForms. Por ejemplo, la prolífica creación de identificadores de fuente mediante 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 IU.

Algunos enlaces útiles:

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

+0

10000 asas por proceso? Esto es nuevo y loco, ¿hay alguna forma de aumentar este límite? –

+0

@AkashKava Esta limitación no es nueva, podría estar equivocado, pero creo que estaba allí desde Windows NT. Y está integrado en la base de código del sistema operativo y no se puede cambiar desde el exterior. –

+0

Estoy de acuerdo, tengo un proceso que excedió los 10k identificadores y cuando trato de crear un nuevo visualizador WPF (var visual = new DrawingVisual()) obtengo el error mencionado anteriormente. –

3

Una vez tuve una excepción similar, cuando se crea un enorme cuadro de imagen. Parece que no pude asignar un Graphics lo suficientemente grande. En realidad, lo que estaba haciendo era dibujar algún tipo de mapa para un juego simple, y tenía una función de acercamiento, que básicamente creaba un búfer más grande y luego volvía a dibujar todos los gráficos en una escala mayor. Jugar con esta función de acercamiento durante un tiempo prolongado o a un nivel lo suficientemente profundo causó esta excepción. Tal vez está creando muchos Gráficos y no eliminándolos, o simplemente un Gráfico lo suficientemente grande como para no ser asignable.

3

Tuve el mismo problema en VB.NET. El motivo era extraño:

En Austria, nuestros sistemas Windows suelen tener una coma y una. como miles-separador. Si esto se tuerce (lo que es estándar en los EE. UU., Creo), Windows arrojará este error. Cambiarlo como debería ser en Austria lo resolvió todo ...

¡Buena suerte!

0

Además, las pérdidas de memoria pueden provocar la excepción. Por ejemplo, una aplicación con 2-3 navegadores web podría alcanzar más de 1 GB en unos pocos minutos, debido a uno de los errores de Internet Explorer como this.

Cuestiones relacionadas