Descartando uma escova estática
-
19-08-2019 - |
Pergunta
Eu estou escrevendo um aplicativo de biorritmo. Para testá-lo eu tenho um formulário com um botão e um PictureBox. Quando clico no botão eu faço
myPictureBox.Image = GetBiorhythm2();
que funciona ok, pela primeira vez, mas no segundo clique que provoca a seguinte exceção:
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
a função de corte-down que faz com que o erro é:
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;
}
se eu comentário-out disposição escova funciona ok, mas eu não estou feliz com isso e desejo de encontrar uma solução alternativa. Você pode me ajudar por favor?
Solução
Parece que você está tentando se desfazer de uma estática, o que causa alguns problemas na próxima vez ele é usado:
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.
Quando você define escova = Brushes.Black, na verdade você está definindo pincel como uma referência (ou ponteiro) para a estática Brushes.Black. Ao descartar-lo, você está escrevendo de forma eficaz:
Brushes.Black.dispose();
Quando você voltar em torno de usar o pincel preto de novo, o tempo de execução diz que você não pode porque ele já foi descartado, e não é um argumento válido para g.FillEllipse ()
A melhor maneira de escrever isso pode ser simplesmente:
g.FillEllipse(Brushes.Black, 3, 3, 2, 2);
Ou, se você quiser ser realmente complexo sobre isso:
Brush brush = Brushes.Black.Clone();
g.FillEllipse( brush, 3, 3, 2, 2 );
brush.Dispose();
Ou se você não se preocupam com coisas olhando errado, apenas comente a brush.Dispose (); linha no seu código original.
Outras dicas
Bruhes.Black é um recurso do sistema, e não se destina para você se desfazer. O tempo de execução administra as escovas na classe pincéis, canetas, e outros tais objetos. Ele cria e descarta esses objetos, conforme necessário, manter os itens utilizados com frequência vivo para que ele não tem que continuamente criar e destruí-los.
A documentação para a classe Brushes diz:
A classe Brushes contém estática propriedades somente leitura que retornam um Escova objecto da cor indicada pela o nome da propriedade. Você costuma fazer não tem que explicitamente dispor do escova retornado por uma propriedade nesta classe, a menos que seja utilizado para construir um novo pincel.
Em suma, não chamar Dispose sobre os objetos fornecidos pelo sistema.
Eu não acho que você precisa chamar .Dispose em escovas estáticas, somente se você criar novos. Embora, pessoalmente, eu usaria o usando a sintaxe .. ou seja:
using (Brush brush = new SolidBrush(...))
{
g.FillEllipse(brush, 3, 3, 2, 2);
}
E você provavelmente deve fazer a mesma coisa com os gráficos objeto que você criar.