Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy is my c# paint method running out of memory?
    text
    copied!<p>I'm new to c#, and trying to learn by writing some simple apps to get familiar with the syntax and .NET library. The most recent miniproject I took on is a polar clock <a href="http://vis.stanford.edu/protovis/ex/clock.html" rel="nofollow noreferrer">like the one found here</a>.</p> <p>One of the problems I noticed early on was that the app would constantly "flicker", which really took away from the presentation, so I read online about how to implement a double buffer, which eliminated this problem, but may or may not have something to do with the problem. Here is my <code>onPaint</code> method; it is called every 33ms (~30 FPS) by a timer control. Most of the rest of the app is simply handlers for dragging the app (since it is frameless and has a transparent background), exiting on double-click, etc.</p> <pre><code> 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); } </code></pre> <p>I thought by disposing of everything at the end of the method I'd be safe, but it doesn't seem to help. Furthermore, the interval between run-time and the OutOfMemoryException isn't constant; once it happened only a few seconds in, but usually it takes a minute or two. Here are some class-wide variable declarations.</p> <pre><code> private Bitmap _backBuffer; private float startAngle = -91F; private float brushWidth = 14; private float spaceStep = 6; </code></pre> <p>And a screenshot (edit: screenshot links to a view with some code present):</p> <p><a href="http://www.ggot.org/inexplicable/pc.jpg" rel="nofollow noreferrer">Screenshot http://www.ggot.org/inexplicable/pc2.jpg</a></p> <p>EDIT: Stacktrace!</p> <pre><code>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&amp; m) at System.Windows.Forms.Control.WndProc(Message&amp; m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp; m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </code></pre> <p>Seems to be the same line it crashed on last time, the main <code>drawArc</code> inside the loop.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload