Утилизация статической кисти
-
19-08-2019 - |
Вопрос
Я пишу приложение для биоритмов. Чтобы проверить это, у меня есть форма с кнопкой и PictureBox. Когда я нажимаю на кнопку, я делаю
myPictureBox.Image = GetBiorhythm2();
В первый раз все работает нормально, но при втором щелчке возникает следующее исключение:
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
функция сокращения, которая вызывает ошибку:
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;
}
Если я закомментирую утилизацию щетки, она будет работать нормально, но я не доволен этим и хочу найти альтернативное решение. Можете ли вы помочь мне, пожалуйста?
Решение
Похоже, вы пытаетесь избавиться от статического, что вызывает некоторые проблемы при следующем использовании:
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.
Когда вы устанавливаете brush = Brushes.Black, вы фактически устанавливаете кисть как ссылку (или указатель) на статический Brushes.Black. Располагая им, вы эффективно пишете:
Brushes.Black.dispose();
Когда вы возвращаетесь, чтобы снова использовать черную кисть, среда выполнения говорит, что вы не можете, потому что она уже удалена и не является допустимым аргументом для g.FillEllipse ()
Лучший способ написать это может быть просто:
g.FillEllipse(Brushes.Black, 3, 3, 2, 2);
Или, если вы хотите быть очень сложным в этом вопросе:
Brush brush = Brushes.Black.Clone();
g.FillEllipse( brush, 3, 3, 2, 2 );
brush.Dispose();
Или, если вам все равно, что выглядит неправильно, просто закомментируйте кисть. Dispose (); строка в исходном коде.
Другие советы
Bruhes.Black является системным ресурсом и не предназначен для вас. Среда выполнения управляет кистями в классе Brushes, Pens и другими подобными объектами. Он создает и удаляет эти объекты по мере необходимости, сохраняя часто используемые элементы живыми, чтобы ему не приходилось постоянно создавать и уничтожать их.
Документация для класса Brushes гласит:
Класс Brushes содержит статические свойства только для чтения, которые возвращают Кисть объекта цвета, обозначенного имя свойства. Вы обычно делаете не должны явно распоряжаться кисть возвращается свойством в этом класс, если он не используется для построения новая кисть.
Короче говоря, не вызывайте Dispose для системных объектов.
Я не думаю, что вам нужно вызывать .Despose для статических кистей, только если вы создаете новые. Хотя лично я бы использовал синтаксис использования .. т.е.
using (Brush brush = new SolidBrush(...))
{
g.FillEllipse(brush, 3, 3, 2, 2);
}
И, вероятно, вы должны сделать то же самое с созданным графическим объектом.