Right Way to Dispose Image/Bitmap and Picturebox

Right way to dispose Image/Bitmap and PictureBox

1:
I dont know if it works in Windows Mobile but try this:

FileStream bitmapFile = new FileStream("mybitmap.bmp", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Image loaded = new Bitmap(bitmapFile);

2: The SolidBrush must be disposed. There is a general rule for dispose. --> "every object, instanciated by you, that implements dispose must be disposed manually, exept when the object is a return/ref/out value"

In this case it is better to use a using statement

using (new objecttodispose){ ..... } 

The using statement will ensure the call of Dispose() in any case (exception for example).

3: Dispose() will free the bitmap ressources.

If I replace an image in a PictureBox control, should I dispose the original image first?

Yes, you should dispose the old object before you create a new image on top of the same variable. By creating a new image with the same variable, you are removing a reference to it. If there are no references to the old object, you are signifying that it should be picked up by the GC (Garbage Collector). Although technically, this "should" eventually result in the memory being freed assuming that the finalizer makes sure that non-managed resources are taken care of, this is a big assumption (You can't even really assume that the finalizer will be called), and it causes more work for the system. Non-default finalizers causes extra work for the GC in terms of garbage collection level promotion, resulting in taking longer for the memory to be deallocated, and the number of times the GC has to run to do so.

This is assuming that is all written to make sure the finalizer handles it. Anytime an object has a Dispose method (anything which implements IDisposable which BitMap does), it should be called before removing reference to the object (falling out of scope, removing reference to the object etc.).

Here is an article on how the Garbage Collector works in .net

http://www.devx.com/dotnet/Article/33167

Here is how MS says the dispose / finalizer should be implemented:

http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx

Where is the proper place to dispose an image

There is a better way to do it. Load the image using FileStream and than assign it to the pictureBox

FileStream bmp = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
Image img = new Bitmap(bmp);
pictureBox1.Image = img;
bmp.Close();

and if you want to clear the picture box, simply

pictureBox1.Image = null;

Dispose Bitmap after showing it in a picturebox control

You're doing it right. The GC is tracking the Bitmap object, and it will release it eventually. The key word being "eventually".

To reclaim the managed bmp instance, it first has to run into memory pressure. That occurs at about 1 MiB for gen-0 collections or so. I'm not sure about the precise number, but the key element is that it's a lot. You're going to have thousands of bitmaps, if not more, before you even get to gen-0 collection - and you usually need a gen-2 to execute finalizers (though take that with a grain of salt, I have no idea where I found that information).

Even when the GC does eventually run (in practice, you'll run out of memory long before that), it will start executing the finalizers on a separate thread. It has no idea about the unmanaged resources, so it has to rely on the finalizer code, which it runs serially. It has no idea how much unmanaged memory is allocated at all, and cannot figure that in its memory checks.

So, the key thing is to always run Dispose on IDisposable objects. The GC might not even get the chance to start the finalizers before you run out of memory, because it's only induced by managed memory pressure. It has no idea about the unmanaged memory (if any). That's not the GCs fault, it really can't tell - after all, in your precise case, the memory is shared. The GC can't know if it even should release that memory - that's up to the Bitmap.Finalize to decide.

That's also the reason why you really want to make everything that uses any IDisposable or unmanaged memory, also IDisposable - to make sure the caller can release the native resource as soon as possible.

This doesn't apply just to unmanaged memory - waiting for the GC to dispose of eg. a file handle or a socket connection is a bad idea, since you really don't want to hold those longer than necessary.

Dispose of a pictureBox image without losing the pictureBox

What is the number of images and total size? I think it is better to load all images in array and assign them to horPicBox than loading them multiple times. To use Dispose first assign horPicBox.Image to temp object, then assign horPicBox.Image to null or next image and call Dispose at the end for the temp object:

Image img = horPicBox.Image;
horPicBox.Image = Image.FromFile(imagePaths[index]);
if ( img != null ) img.Dispose();

What happens to a Bitmap in a PictureBox once Image is set to another Bitmap?

The PictureBox can't know whether you want the image disposed--you might be using it elsewhere in your app. So it doesn't explicitly Dispose it. If the PictureBox held the last reference to it, it becomes eligible for garbage collection, and Dispose will be called as part of finalization, but when that happens is up to the garbage collector. In the meantime, the not-yet-disposed Bitmap is consuming unmanaged resources and most likely holding a stream open that will prevent modifications to the source file, so letting things get cleaned up "whenever" is bad practice.

If you know you're done with the Bitmap at the time of changing what PictureBox.Image points to, add an extra couple lines right there to dispose of the old one and you're done:

Image tmp = myPictureBox.Image;
myPictureBox.Image = newImage;
if (tmp != null)
{
tmp.Dispose();
}

What is the best practice when it comes to dispose image object in c#?

You should always dispose the disposable instances somewhere. So take the latter.

You could make it a bit more readable:

       using (MemoryStream stream = new MemoryStream(ImageBytes))
using(var newImage = System.Drawing.Image.FromStream(stream))
{
// ...

Note: It doesn't make sense to have the variable declared outside the using statement. You shouldn't use it outside.

Picturebox.Image.Dispose is causing ArgumentException?

I suspect the issue may be that the disposed Image is still assigned to the Image property of the PictureBox and tries to get repainted. I would suggest assigning the Image to a local variable, setting the Image property of the PictureBox to Nothing and then disposing the Image.



Related Topics



Leave a reply



Submit