Improper use of InteropBitmap can cause a memory leak

I've been using InteropBitmap in my GdiTextBlock. The control creates a new GDI+ Bitmap every measure pass, which it then converts to a WPF BitmapSource using the Imaging.CreateBitmapSourceFromHBitmap() method (this method returns an InteropBitmap).

After playing with the control for a while I noticed that the process' working set is constantly increasing. I realized I must have a problem with my bitmap conversion. So, I set out to seek an alternative solution, and I came up with a simple way of creating a BitmapSource directly from a GDI+ Bitmap. (See attached. I've also updated the GdiTextBlock post.)

After some more digging, I found out that the leakage was entirely my fault. To use the CreateBitmapSourceFromHBitmap() method, you have to convert the GDI+ bitmap to an HBITMAP by calling the Bitmap.GetHbitmap() method. Its documentation clearly states that "You are responsible for calling the GDI DeleteObject method to free the memory used by the GDI bitmap object." Well, there you have it.

I decided to benchmark the two options. Here are the results:

Interop Bitmap No Delete
------------------------
Time: 00:00:01.5989544, Process Memory: 396,936 KB

Interop Bitmap With Delete
--------------------------
Time: 00:00:01.5158545, Process Memory: 9,056 KB

Alternate
---------
Time: 00:00:00.5108011, Process Memory: 9,080 KB

It would seem that the alternate method is preferable even after deleting the HBITMAP. I think the reason for the (time) overhead is that the GDI+ bitmap needs to be converted to an HBITMAP, and then converted to a WPF bitmap, while in the alternate method, we skip the middleman.

Side note: I'm using a new .NET 3.5 SP1 feature, which allows forcing a garbage collection using the GC.Collect() method (which has a few new overloads as well). Can be pretty useful for benchmarking or debugging.

Published 10-22-2008 11:29 AM by aelij
Filed under:

Comments

# re: Improper use of InteropBitmap can cause a memory leak

Tuesday, March 03, 2009 9:10 AM by Aaron

This helped me out so much - thank you!

# re: Improper use of InteropBitmap can cause a memory leak

Tuesday, August 11, 2009 2:28 AM by Sreekanth

This is a superb article....thanks buddy...

# re: Improper use of InteropBitmap can cause a memory leak

Friday, July 09, 2010 6:26 AM by Keith

I have been looking for months (literally) for an alternative to the MSDN prescription of using GetHbitmap to derive a BitmapSource from a GDI+ Bitmap. In the application that I'm working on, I have to repaint a 1000x1000 bitmap a minimum of 10 times per second and more if possible. Using the MSDN prescription, it was taking ~20 milliseconds just to move the final GDI+ bitmap into a BitmapSource so WPF could render it. Using your alternate method, that reduced to ~5 milliseconds. That's a 75% increase!!! Thanks so much for posting this article.

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Please add 1 and 5 and type the answer here:
Powered by Community Server (Non-Commercial Edition), by Telligent Systems