本文介绍了为什么我的c#paint方法内存不足?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是c#的新手,并尝试通过编写一些简单的应用程序来学习以熟悉语法和.NET库.我最近进行的小型项目是一个极地时钟像在这里找到的那​​个

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 like the one found here.

我很早就注意到的问题之一是该应用程序会不断闪烁",这确实使演示文稿望而却步,所以我在线阅读了有关如何实现双缓冲的内容,从而消除了此问题,但可能会或可能与问题无关.这是我的onPaint方法;它由计时器控件每33ms(〜30 FPS)调用一次.该应用程序的大多数其余部分仅是用于拖动该应用程序的处理程序(因为它是无框架的并且具有透明的背景),双击退出等.

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 onPaint 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.

    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之间的时间间隔不是恒定的.一旦发生仅几秒钟,但通常需要一两分钟.这是一些类范围的变量声明.

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.

    private Bitmap _backBuffer;

    private float startAngle = -91F;
    private float brushWidth = 14;
    private float spaceStep = 6;

还有一个屏幕截图(屏幕截图链接到存在一些代码的视图):

And a screenshot (edit: screenshot links to a view with some code present):



Stacktrace!

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.

Seems to be the same line it crashed on last time, the main drawArc inside the loop.

推荐答案

对于其他任何人,可以通过Google查找此页面:

Just for anyone else, finding this page via Google:

如果使用System.Drawing.DrawArc,则可能导致System.OutOfMemoryException异常.如果尝试打印小角度,也可能是错误.

A possible cause of System.OutOfMemoryException if you use System.Drawing.DrawArc could also be a bug if you try to print small angles.

对于角度< 1此错误在我的代码中发生过几次.

For angles < 1 this bug occured several times in my code.

另请参阅:

http://connect.microsoft .com/VisualStudio/feedback/details/121532/drawarc-out-of-memory-exception-on-small-arcs

这篇关于为什么我的c#paint方法内存不足?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 13:22
查看更多