2011-06-28 9 views
7

Mi motor de gráficos de aplicaciones arroja estas excepciones. Todos son consumidos por un bloque de catch vacío. En los primeros días encontré uno que no estaba atrapado (asociado con la ampliación del lapicero, según recuerdo). Lo rodeé con try y un bloque catch vacío. Parece que estas excepciones no tienen ningún efecto en el dibujo producido. He leído algo sobre esto sin realmente entender o llegar al fondo del asunto.Excepción System.Drawing Out of Memory

Así que a mis preguntas:

  1. ¿por qué estos sean lanzados si se pueden consumir con seguridad? y
  2. ¿Es seguro ignorarlos? Me preocupa que cada uno tenga algún efecto oculto. Tengo fugas de memoria que nunca he encontrado, por ejemplo.
+0

¿Está desechando cosas como bolígrafos, pinceles, gráficos, imágenes después de usarlos? –

+4

Se lanzan para decirte que tu código está roto. Atraparlos con una cláusula de captura vacía no soluciona tu código, simplemente dispara al mensajero. –

+1

GDI + a veces arroja una excepción de falta de memoria cuando en realidad es un argumento no válido. No estoy seguro si eso es relevante aquí. – CodesInChaos

Respuesta

19

He visto System.Drawing lanzar OutOfMemoryExceptions incluso cuando no está sin memoria. Algunas funciones de GDI + aparentemente están devolviendo un código de error estúpido.

IIRC, obtendrá una OutOfMemoryException si intenta utilizar un LinearGradientBrush para rellenar un rectángulo cuyo ancho o alto es cero. Puede haber otras condiciones también, pero esta es la principal con la que nos encontramos.

En ese caso, no hay necesidad de probar/atrapar. Simplemente agregue una declaración if a su código de dibujo, y no complete el rectángulo si el ancho o alto es cero.

Actualización: De acuerdo con los comentarios en this answer, también puede ocurrir si intenta cargar un archivo de imagen dañado. Para eso, no tendrías más remedio que intentar/atrapar.

Probablemente esté seguro atrapando OutOfMemoryExceptions de GDI +, pero mantenga los bloques de prueba lo más pequeños posible.Considere registrar las excepciones, para que pueda analizar los registros y agregar código defensivo cuando sea posible. No desea enmascarar un real OutOfMemoryException, pero tampoco desea que un estúpido código de error GDI + bloquee su aplicación.

+0

No hay ningún archivo de imagen involucrado en el dibujo. Una gran idea para usar el registro. La aplicación tiene un registrador, así que agregaré algo de registro a las cláusulas catch y veré qué aparece. Si parece desagradable agregaré algún código defensivo. – ScruffyDuck

+0

¡Gracias desde 2016! ¡Salvaste mi día! – Genius

+0

¿Qué sucede si necesita dibujar una línea de degradado vertical u horizontal? ¡Entonces el rectángulo tendría un ancho o altura cero! – AaronF

2

Es un muy mal excepción: http://msdn.microsoft.com/en-us/library/system.outofmemoryexception.aspx .. la memoria no es suficiente para continuar la ejecución del programa.

A menudo encontrará que si ha asignado tantas operaciones/asignaciones 'simples' a este mensaje, la aplicación fallará poco después. Si se trata de una asignación masiva que está fallando, es posible que pueda continuar.

Si la aplicación hace algo importante, debe intentar cerrar las cosas correctamente.

Para responder a sus preguntas de forma explícita:

  1. Están tirado por lo que la aplicación tiene la oportunidad de reaccionar/recuperarse: algunas asignaciones de memoria (10 GB por valor de los objetos) se podría esperar a fallar en muchas situaciones, tal vez un accidente de aplicación de una línea (int[] x = new int[5368709120]; equivalente) en realidad debería lanzar una excepción en lugar de estrellarse todo

  2. no debe haber ningún efecto oculto, pero si falla una asignación, entonces tal vez la próxima vez que desee un string u otro útil objeto de alguna pequeña manera asignada para la operación general de la aplicación: las cosas pueden volverse inestables. Dicho en función del entorno, es posible obtener esta excepción en cualquier momento ..

Editar: Cualquiera que lea esto también se debe tener en cuenta que, al parecer, en GDI + lanza esta excepción también por otras razones.

+0

Gracias - para ser honesto, nunca hemos tenido la aplicación caerse. Tenemos alrededor de 30,000 usuarios y esto no se ha informado. Sin embargo, si miro el registro de salida en VS, veo varias docenas de 'Excepciones de primera oportunidad' de este tipo que están siendo consumidas por la cláusula (s) de captura vacía – ScruffyDuck

+2

OOM significa algo más cuando GDI + lo lanza. Las excepciones GDI + son bastante descuidadas. –

+0

Normalmente eso es cierto, pero GDI + arroja OutOfMemoryExceptions incluso cuando no está sin memoria. Lo he visto. Algunas funciones devuelven un código de error malo o algo así. –

0

Intenté la solución 'Joe White' sugerida y eso fue todo. Lanzó una OutOfMemoryException porque el ancho y la altura del rectángulo eran 0. En mi caso, la ventana se minimizó cuando se produjo la excepción.

Aquí hay un ejemplo;

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 

    Using e 
     ##Add conditions to avoid OutOfMemoryException## 
     If (Not ClientRectangle.Width = 0) And (Not ClientRectangle.Height = 0) Then 
      Using rect As GraphicsPath = New GraphicsPath() 
       rect.AddRectangle(ClientRectangle) 

       Using gb As New PathGradientBrush(rect) 
        gb.WrapMode = WrapMode.Tile 
        gb.SurroundColors = New Color() {GradientColors(1), GradientColors(0), GradientColors(2)} 
        gb.CenterColor = GradientColors(0) 
        gb.SetSigmaBellShape(0.5F) 
        e.Graphics.FillPath(gb, rect) 
       End Using 
      End Using 
     End If 
    End Using 

End Sub 
Cuestiones relacionadas