Desechar un cepillo estático
-
19-08-2019 - |
Pregunta
Estoy escribiendo una aplicación de biorritmo. Para probarlo, tengo un formulario con un botón y un PictureBox. Cuando hago clic en el botón que hago
myPictureBox.Image = GetBiorhythm2();
Que funciona bien por primera vez, pero en el segundo clic causa la siguiente excepción:
System.ArgumentException: Parameter is not valid.
at System.Drawing.Graphics.CheckErrorStatus
at System.Drawing.Graphics.FillEllipse
at Larifari.Biorhythm.Biorhythm.GetBiorhythm2 in c:\delo\Horoskop\Biorhythm.cs:line 157
at Larifari.test.Button1Click in c:\delo\Horoskop\test.Designer.cs:line 169
at System.Windows.Forms.Control.OnClick
at System.Windows.Forms.Button.OnClick
at System.Windows.Forms.Button.OnMouseUp
at System.Windows.Forms.Control.WmMouseUp
at System.Windows.Forms.Control.WndProc
at System.Windows.Forms.ButtonBase.WndProc
at System.Windows.Forms.Button.WndProc
at ControlNativeWindow.OnMessage
at ControlNativeWindow.WndProc
at System.Windows.Forms.NativeWindow.DebuggableCallback
at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
at ThreadContext.RunMessageLoopInner
at ThreadContext.RunMessageLoop
at System.Windows.Forms.Application.Run
at Larifari.test.Main in c:\delo\Horoskop\test.cs:line 20
la función de corte que causa el error es:
public static Image GetBiorhythm2() {
Bitmap bmp = new Bitmap(600, 300);
Image img = bmp;
Graphics g = Graphics.FromImage(img);
Brush brush = Brushes.Black;
g.FillEllipse(brush, 3, 3, 2, 2); //Here the exception is thrown on the second call to the function
brush.Dispose(); //If i comment this out, it works ok.
return img;
}
si comento la eliminación del cepillo, funciona bien, pero no estoy contento con eso y deseo encontrar una solución alternativa. ¿Me pueden ayudar por favor?
Solución
Parece que está tratando de deshacerse de una estática, lo que causa algunos problemas la próxima vez que se use:
Brush brush = Brushes.Black;
g.FillEllipse(brush, 3, 3, 2, 2); //Here the exception is thrown on the second call to the function
brush.Dispose(); //If i comment this out, it works ok.
Cuando configuras brush = Brushes.Black, en realidad estás configurando brush como referencia (o puntero) a los Brushes.Black estáticos. Al eliminarlo, está escribiendo efectivamente:
Brushes.Black.dispose();
Cuando vuelves a usar el pincel negro nuevamente, el tiempo de ejecución dice que no puedes porque ya se ha eliminado y no es un argumento válido para g.FillEllipse ()
Una mejor manera de escribir esto podría ser simplemente:
g.FillEllipse(Brushes.Black, 3, 3, 2, 2);
O, si quieres ser realmente complejo al respecto:
Brush brush = Brushes.Black.Clone();
g.FillEllipse( brush, 3, 3, 2, 2 );
brush.Dispose();
O si no le importa que las cosas se vean mal, simplemente comente el pincel. Dispose (); línea en su código original.
Otros consejos
Bruhes.Black es un recurso del sistema y no está destinado a que lo deseche. El tiempo de ejecución administra los pinceles en la clase Pinceles, los Bolígrafos y otros objetos similares. Crea y dispone esos objetos según sea necesario, manteniendo vivos los artículos de uso frecuente para que no tenga que crearlos y destruirlos continuamente.
La documentación para la clase Brushes dice:
La clase Brushes contiene estática propiedades de solo lectura que devuelven un Pincel objeto del color indicado por El nombre de la propiedad. Normalmente haces no tener que deshacerse explícitamente de cepillo devuelto por una propiedad en este clase, a menos que se use para construir un nuevo pincel.
En resumen, no llame a Dispose en los objetos proporcionados por el sistema.
No creo que necesites llamar. Dispón en pinceles estáticos, solo si creas otros nuevos. Aunque, personalmente, usaría la sintaxis de uso ... es decir:
using (Brush brush = new SolidBrush(...))
{
g.FillEllipse(brush, 3, 3, 2, 2);
}
Y probablemente deberías hacer lo mismo con el objeto gráfico que creas.