I'm trying to use a PictureBox to create an animation in a Windows Forms app (C#) by drawing on the Bitmap using Graphics. Unfortunately, it looks like I am leaking memory somewhere or allocating too much based on this error:
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
Additional information: Out of memory.
This is the source code. Desired behavior is a popup with a glitchy animation.
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 AnimationApp
{
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;
}
}
}
Thank you for any help.
SolidBrushes, that's for sure. You need to dispose of them. The thing I'm not sure about is if you'd also need to dispose explicitly of the oldpictureBox1.Imageimage. 100 ticks per seconds is also pretty excessive...SolidBrushshould be either inusingstatements like yourGraphicsor be declared on a separate line so you can callDisposeon em. Or even better, declare them at class level and reuse the same brushes instead of creating a new one each time. For thepictureBox, you can look at this answer. And you can change yourTickto 33 for about 30FPS, which should be fluid enough and less taxing on the hardware. Not sure about the picturebox though.OutOfMemoryExceptionfor me. So apparently it does leak, albeit due to late triggered GC (see Ian answer below). Addingif (pictureBox1.Image != null) pictureBox1.Image.Dispose();right beforepictureBox1.Image = bmp;would probably solve the out of memory issue...