有一段时间,我在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)
{
}
}
}
感谢您的帮助。
答案 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之前;可能会解决内存不足的问题...