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.

Attachment: InteropBitmapLeak.zip

Tagged with:
 

3 Responses to Improper use of InteropBitmap can cause a memory leak

  1. Aaron says:

    This helped me out so much – thank you!

  2. Sreekanth says:

    This is a superb article….thanks buddy…

  3. Keith says:

    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 1000×1000 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.

Set your Twitter account name in your settings to use the TwitterBar Section.