Я новичок в C# и пытаюсь научиться писать простые приложения, чтобы ознакомиться с синтаксисом и библиотекой .NET. Самый последний минипроект, который я взял, - полярные часы like the one found here.Почему у моего метода рисования C# заканчивается память?
Одна из проблем, которые я заметил на ранней стадии, заключалась в том, что приложение будет постоянно «мерцать», что действительно отвлекает от презентации, поэтому я читал онлайн о том, как реализовать двойной буфер, который устранил эту проблему, но может или возможно, не имеет никакого отношения к проблеме. Вот мой метод onPaint
; он вызывается каждые 33 мс (~ 30 FPS) с помощью таймера. Большая часть остальной части приложения является просто обработчики для перетаскивания приложения (так как это бескаркасные и имеет прозрачный фон), выход на двойной щелчок и т.д.
protected override void OnPaint(PaintEventArgs e) {
DateTime now = DateTime.Now;
float secondAngle = now.Second/60F;
secondAngle += (now.Millisecond/1000F) * (1F/60F);
float minuteAngle = now.Minute/60F;
minuteAngle += secondAngle/60F;
float hourAngle = now.Hour/24F;
hourAngle += minuteAngle/60F;
float dayOfYearAngle = now.DayOfYear/(365F + (now.Year % 4 == 0 ? 1F : 0F));
dayOfYearAngle += hourAngle/24F;
float dayOfWeekAngle = (float)(now.DayOfWeek + 1)/7F;
dayOfWeekAngle += hourAngle/24F;
float dayOfMonthAngle = (float)now.Day/(float)DateTime.DaysInMonth(now.Year, now.Month);
dayOfMonthAngle += hourAngle/24F;
float monthAngle = now.Month/12F;
monthAngle += dayOfMonthAngle/(float)DateTime.DaysInMonth(now.Year, now.Month);
float currentPos = brushWidth/2F;
float[] angles = {
secondAngle, minuteAngle,
hourAngle, dayOfYearAngle,
dayOfWeekAngle, dayOfMonthAngle,
monthAngle
};
SolidBrush DateInfo = new SolidBrush(Color.Black);
SolidBrush background = new SolidBrush(Color.Gray);
Pen lineColor = new Pen(Color.Blue, brushWidth);
Font DateFont = new Font("Arial", 12);
if (_backBuffer == null) {
_backBuffer = new Bitmap(this.Width, this.Height);
}
Graphics g = Graphics.FromImage(_backBuffer);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
try {
g.Clear(Color.White);
if (_mouseIsOver) {
g.FillEllipse(background, new Rectangle(0, 0, this.Width, this.Height));
}
foreach (float angle in angles) {
g.DrawArc(
lineColor,
currentPos, currentPos,
this.Height - currentPos * 2, this.Width - currentPos * 2,
startAngle, angle * 360F
);
currentPos += brushWidth + spaceStep;
}
// Text - Seconds
g.DrawString(String.Format("{0:D2} s", now.Second), DateFont, DateInfo, new PointF(115F, 0F));
g.DrawString(String.Format("{0:D2} m", now.Minute), DateFont, DateInfo, new PointF(115F, 20F));
g.DrawString(String.Format("{0:D2} h", now.Hour), DateFont, DateInfo, new PointF(115F, 40F));
g.DrawString(String.Format("{0:D3}", now.DayOfYear), DateFont, DateInfo, new PointF(115F, 60F));
g.DrawString(now.ToString("ddd"), DateFont, DateInfo, new PointF(115F, 80F));
g.DrawString(String.Format("{0:D2} d", now.Day), DateFont, DateInfo, new PointF(115F, 100F));
g.DrawString(now.ToString("MMM"), DateFont, DateInfo, new PointF(115F, 120F));
g.DrawString(now.ToString("yyyy"), DateFont, DateInfo, new PointF(115F, 140F));
e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0);
}
finally {
g.Dispose();
DateInfo.Dispose();
background.Dispose();
DateFont.Dispose();
lineColor.Dispose();
}
//base.OnPaint(e);
}
protected override void OnPaintBackground(PaintEventArgs e) {
//base.OnPaintBackground(e);
}
protected override void OnResize(EventArgs e) {
if (_backBuffer != null) {
_backBuffer.Dispose();
_backBuffer = null;
}
base.OnResize(e);
}
я думал, что, избавляясь от всего в конце метода я был бы в безопасности, но он, похоже, не помогает. Кроме того, интервал между временем выполнения и исключением OutOfMemoryException не является постоянным; как только это произошло всего несколько секунд, но обычно это занимает минуту или две. Вот некоторые объявления переменных класса.
private Bitmap _backBuffer;
private float startAngle = -91F;
private float brushWidth = 14;
private float spaceStep = 6;
и скриншот (редактирование: скриншот ссылки на вид с некоторым кодом присутствует):
Screenshot http://www.ggot.org/inexplicable/pc2.jpg
EDIT: StackTrace!
System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
at System.Drawing.Graphics.DrawArc(Pen pen, Single x, Single y, Single width, Single height, Single startAngle, Single sweepAngle)
at PolarClock.clockActual.OnPaint(PaintEventArgs e) in C:\Redacted\PolarClock\clockActual.cs:line 111
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(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)
Кажется, в той же строке, что разбитый на последний раз, главный drawArc
внутри цикла.
Пожалуйста, кадрировать снимки экрана, чтобы они не являются больше, чем необходимо. – Gabe
@Gabe: Готово; Я использовал более крупный, чтобы показать дополнительный код, поэтому я сделал новый скриншот ссылкой на более старый. – Dereleased
Согласно комментариям в http://msdn.microsoft.com/en-us/library/system.drawing.graphics.drawarc(VS.90).aspx есть ошибка в drawArc, когда arc i меньше 2 пикселей или 3.5 развертки градусов. –