.Net and Bitmap are not automatically deleted by GC when there is no memory

I am wondering how it allocates and deletes the memory allocated for bitmap images in .NET.

When I make a lot of raster creations in loops in a function and call them sequentially, it will work until at some point the bitmap can allocate memory, giving an exception "Invalid parameter" for the specified size.

If I call the garbage collector while it works.

With the following code, you can recompose the error:

class BitmapObject { public bool Visible { get { return enb; } set { enb = value; } } private bool enb; private Bitmap bmp; public BitmapObject(int i, bool en) { enb = en; bmp = new Bitmap(i, i); } } class Pool<T> where T : BitmapObject { List<T> preallocatedBitmaps = new List<T>(); public void Fill() { Random r = new Random(); for (int i = 0; i < 500; i++) { BitmapObject item = new BitmapObject(500, r.NextDouble() > 0.5); preallocatedBitmaps.Add(item as T); } } public IEnumerable<T> Objects { get { foreach (T component in this.preallocatedBitmaps) { if (component.Visible) { yield return (T)component; } } } } } static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { for (int i = 0; i < 10; i++ ) { Test(); // without this it breaks //GC.Collect(); //GC.WaitForPendingFinalizers(); } Console.ReadKey(); } private static void Test() { Pool<BitmapObject> pool = new Pool<BitmapObject>(); pool.Fill(); for (int i = 0; i < 100; i++) { var visBitmaps = pool.Objects; // do something } } } 
+8
source share
3 answers

The .NET Bitmap class “encapsulates GDI + bitmap”, which means you have to call Dispose on Bitmap when you are done with it.

"Always call Dispose before you release the last link to the Image. Otherwise, the resources will not be freed until the garbage collector calls the image object Completion Method."

+14
source

The Bitmap class is inevitably one where you should stop ignoring this IDisposable. This is a small wrapper class around a GDI + object. GDI + is unmanaged code. The bitmap takes up unmanaged memory. A lot when the bitmap is big.

The .NET garbage collector ensures that unmanaged system resources are released using the finalizer thread. The problem is that it only works when you create enough managed objects to start garbage collection. This will not work well for the Bitmap class, you can create many thousands of them before generation # 0 of the collected garbage heap is full. Before you can reach it, you will run out of unmanaged memory.

Life time management of the used bitmap images is required. Call the Dispose () method when you are no longer using it. This is not always a golden decision; you may have to rethink your approach if you have too many live bitmaps. The next solution will be a 64-bit operating system.

+17
source

Why don't you use the using keyword. Just encapsulate your Bitmap object in it, and Compiler will ensure that the Dispose method is called.

Its just a syntax shortcut for

 try { ... } finally { ...Dispose(); } 
+1
source

All Articles