.NET Framework Bookmark and Share   
 index > Common Language Runtime > How can i release resources used by Bitmap
 

How can i release resources used by Bitmap

Hi, can anyone help me about releasing resources used by bitmap?

i have some usercontrols in my app and they displays an image from mediafiles.

I get images as thumbnails with code part below

Bitmap bmp = new Bitmap(posterFramePath);

Image img = bmp.GetThumbnailImage(120, 96, null, IntPtr.Zero);

bmp.Dispose();

pictureBox1.Image = img;

works fine and displays thumbnails.However, when i refresh controls(dispose and recreate all) memory inreases about 2 MB for 20 user controls. i think bmp.dispose does not somehow. For any offers i'll be glad to you.

Koray Samsun
I tried to reproduce your problem but couldn't. Heap usage bounced back and forth between 800 and 1800 KB on this test program, clearly showing the garbage collector doing its job. Working set size bounced between 22 and 40MB, showing that unmanaged memory is getting released to:

UserControl1:
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}
private void UserControl1_Load(object sender, EventArgs e) {
Bitmap bmp = new Bitmap(@"c:\temp\test.bmp");
Image img = bmp.GetThumbnailImage(128, 128, null, IntPtr.Zero);
if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
pictureBox1.Image = img;
bmp.Dispose();
}
}

Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
addUserControls();
}
private void addUserControls() {
for (int ix = 0; ix < 100; ++ix) {
UserControl1 usr = new UserControl1();
usr.Left = usr.Top = ix;
this.Controls.Add(usr);
}
}
private void removeUserControls() {
int ix = 0;
while (ix < this.Controls.Count) {
Control ctl = this.Controls[ix];
if (ctl is UserControl1) {
this.Controls.RemoveAt(ix);
ctl.Dispose();
}
else ix++;
}
}
private void button1_Click(object sender, EventArgs e) {
removeUserControls();
addUserControls();
label1.Text = (GC.GetTotalMemory(false) / 1024).ToString();
label2.Text = (System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024).ToString();
}
}

Make sure you get the code right that removes and disposes the controls, it can be tricky...
nobugz

Are you disposing the thumbnail images too? Keep in mind that they will take up a fair bot of space, by my calculations 20 120x96x32bit images would take up 921.6 KB, which is already half of your memory increase.

Sean Hederman

Thanks for reply, i dispose thumbnail images on dispose method like

pictureBox1.Image.Dispose()

Nothing changes

Koray Samsun

Okay, the next thing to check is finding out exactly where your memory leak is. If you create an empty project, load up 20 Bitmaps and then dispose them, do you get the leak? If not, then add the code to get the thumbnails, dispose them and check for a leak. If still not... you get the idea I'm sure.

Simply put you have too many things that could be causing the leak. Another possibility is that it is not a leak at all. If the leak does not grow beyond 2MB no matter what you do, then it could very well just be the libraries and runtime caching information they need.

Sean Hederman

Hi,

first make sure that you no longer have any refernces to the image or thumbnail i.e. set pictureBox1.Image = null If you have any references then the GC will not be able to collect up these images. Secondly just because you call Dispose on an object does not mean the memory will be freed. What really needs to happen is for the GC to run but this is undeterministic it will run when it thinks it needs to run so it is perfectly acceptable for you memory use to continue increasing until the GC thinks it is necessary to reclaim what it can. If you really want to find out if you have a leak you can force the GC by calling:

GC.Collect();

GC.WaitForPendingFinalizers();

Making sure that you have no references to any of your images and that you previously called Dispose on all of the objects (if you did not then it will take 2 GC calls to clean up the associated objects due to the finalizers being run)

You should now see your memory usage go down. However there is no need to call this method in real life since the GC will run when it wants to an normally it knows best. You can also use the CLR Profiler (search for it) that will show you exactly how much memory you application is taking and the types of objects that are using the memory.

Mark.

Mark Dawson

" Secondly just because you call Dispose on an object does not mean the memory will be freed."

The managed memory used by the object itself is not freed indeed. But the unmanaged memory used by the Bitmap class should be released when Dispose is called. That's the whole point of using Dispose after all. Since the managed memory used by the Bitmap class is something like 12 bytes this cannot possible account for 2 megabytes.

Mike Danes
I tried to reproduce your problem but couldn't. Heap usage bounced back and forth between 800 and 1800 KB on this test program, clearly showing the garbage collector doing its job. Working set size bounced between 22 and 40MB, showing that unmanaged memory is getting released to:

UserControl1:
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}
private void UserControl1_Load(object sender, EventArgs e) {
Bitmap bmp = new Bitmap(@"c:\temp\test.bmp");
Image img = bmp.GetThumbnailImage(128, 128, null, IntPtr.Zero);
if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
pictureBox1.Image = img;
bmp.Dispose();
}
}

Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
addUserControls();
}
private void addUserControls() {
for (int ix = 0; ix < 100; ++ix) {
UserControl1 usr = new UserControl1();
usr.Left = usr.Top = ix;
this.Controls.Add(usr);
}
}
private void removeUserControls() {
int ix = 0;
while (ix < this.Controls.Count) {
Control ctl = this.Controls[ix];
if (ctl is UserControl1) {
this.Controls.RemoveAt(ix);
ctl.Dispose();
}
else ix++;
}
}
private void button1_Click(object sender, EventArgs e) {
removeUserControls();
addUserControls();
label1.Text = (GC.GetTotalMemory(false) / 1024).ToString();
label2.Text = (System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024).ToString();
}
}

Make sure you get the code right that removes and disposes the controls, it can be tricky...
nobugz

Thanks, everyone. I figured that i make wrong while removing controls from nobugz code. I was just using panel.Controls.Clear. Correct it and not at that moment but later memory decreases.

Koray Samsun

You can use google to search for other answers

Custom Search

More Threads

• Generating SampleKey.snk File - Access Denied
• File access permissions needed by Xml.Serialization.Compiler
• Why can't I deserialize my Type?
• Execute .NET code written by end-user to customize a procedure
• What is ArrayListDebugView?
• embedding a windows form control into a web page
• utility to detect unmanged resources leaks
• Cleanup .NET COM component after "unexpected end" of unmanaged host application
• Business Object having Database related methods
• Access security status (firewall, av)