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.