C#错误:类型' System.OutOfMemoryException'的未处理异常发生在System.Drawing.dll中

时间:2015-12-18 02:43:16

标签: c#

有一段时间,我在C#中使用了pictureBox来为模拟和其他事情做动画。现在我正在编写代码来欺骗一个朋友(他只需要点击alt-f4来关闭它,没什么大不了的。)但是我一直收到这个错误:

An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
Additional information: Out of memory.

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EnrogSecurityBreach
{
    public partial class Form1 : Form
{
    Timer timer = new Timer();
    Form1 form1;
    //Bitmap bmp;
    public Form1()
    {
        InitializeComponent();
        form1 = this;
        form1.TransparencyKey = Color.White;
        FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;



        pictureBox1.Left = 0;
        pictureBox1.Top = 0;
        pictureBox1.Width = Screen.PrimaryScreen.Bounds.Width;
        pictureBox1.Height = Screen.PrimaryScreen.Bounds.Height;
        timer.Enabled = true;
        timer.Interval = 10;
        timer.Tick += timer_tick;

    }
    Random rand = new Random();
    int partsection = 0;
    int waitint = 0;
    int ran1 = 0;
    int ran2 = 0;
    int intensifies = 0;
    public void timer_tick(object e, EventArgs ea)
    {
        Bitmap bmp;
        bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);

        using (Graphics g = Graphics.FromImage(bmp))
        {
            if (partsection == -1)
            {

            }

            else if (partsection<300)
            {
                if (waitint == 0)
                {

                    ran1 = rand.Next(0, pictureBox1.Width);
                            ran2 = rand.Next(0, pictureBox1.Width);
                    waitint = 10;
                }
                else
                {
                    waitint--;
                }

                g.FillRectangle(new SolidBrush(Color.Green), (float)ran1, (float)0, 3, pictureBox1.Height);
                g.FillRectangle(new SolidBrush(Color.DarkGreen), (float)ran2, (float)0, 3, pictureBox1.Height);

                partsection++;
            }
            else if (partsection < 1000)
            {
                if (intensifies < 255)
                {
                    intensifies++;

                }
                else
                {

                }
                g.FillRectangle(new SolidBrush(Color.FromArgb(intensifies,Color.Black)), (float)0, (float)0, pictureBox1.Width, pictureBox1.Height);
            }

        }
        pictureBox1.Image = bmp;

    }
    private void Form1_Load(object sender, EventArgs e)
    {

    }
}
}

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

您的位图需要声明为表单的实例变量。

修改

具体来说,取消注释类实例变量中Bitmap的声明。接下来,添加以下代码:

    protected override void OnResize(EventArgs e)
    {
        pictureBox1.Left = 0;
        pictureBox1.Top = 0;
        pictureBox1.Width = Screen.PrimaryScreen.Bounds.Width;
        pictureBox1.Height = Screen.PrimaryScreen.Bounds.Height;
        bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        base.OnResize(e);
    }

为什么呢?因为您需要在表单调整大小时调整图片框的大小,或者用户更改屏幕分辨率。现在,Bitmap仅被声明一次。我运行代码几分钟没有任何不良影响。

BTW,pictureBox1调整大小代码已从构造函数中删除。

答案 1 :(得分:1)

这是因为您使用的某些资源是非托管的,并且您没有将其放在using块下,或者在使用后处置非托管资源的任何替代方法。由于这个原因,内存泄露了。

例如,这些行,

g.FillRectangle(new SolidBrush(Color.Green), (float)ran1, (float)0, 3, pictureBox1.Height);
g.FillRectangle(new SolidBrush(Color.DarkGreen), (float)ran2, (float)0, 3, pictureBox1.Height);

可以更改为

using (SolidBrush greenBrush = new SolidBrush(Color.Green))
using (SolidBrush darkGreenBrush = new SolidBrush(Color.DarkGreen)) {
    g.FillRectangle(greenBrush , (float)ran1, (float)0, 3, pictureBox1.Height);
    g.FillRectangle(darkGreenBrush, (float)ran2, (float)0, 3, pictureBox1.Height);
}

同样,这一行

g.FillRectangle(new SolidBrush(Color.FromArgb(intensifies,Color.Black)), (float)0, (float)0, pictureBox1.Width, pictureBox1.Height);

到此

using (SolidBrush blackBrush = new SolidBrush(Color.FromArgb(intensifies, Color.Black)))
    g.FillRectangle(blackBrush, (float)0, (float)0, pictureBox1.Width, pictureBox1.Height);

另一个建议是你应该检查System.Drawing上的非托管资源。由于您可能会显示更多非托管资源但未指出 - 或者 - 您没有提出问题但实际上是代码的其他部分。

Here更多是非托管资源:

以下是Bitmap导致泄漏的可能性的另一种解释(由于小型托管Bitmap类包装器,可能导致内存不足,因为垃圾收集器是后期触发的),见Hans Passant先生的explanation

答案 2 :(得分:0)

@IronGeek找到了解决方案:

  

将代码更改为使用固定屏幕分辨率3840x2160,它会为我抛出OutOfMemoryException。显然它确实泄漏了,虽然是由于后期触发GC(见下面的Ian答案)。添加if(pictureBox1.Image!= null)pictureBox1.Image.Dispose();就在pictureBox1.Image = bmp之前;可能会解决内存不足的问题...