6
votes

I'm trying to figure out how to release a WriteableBitmap memory.

In the next section of code I fill the backbuffer of a WriteableBitmap with a really large amount of data from "BigImage" (3600 * 4800 px, just for testing) If I comment the lines where bitmap and image are equaled to null, the memory it´s not release and the application consumes ~230 MB, even when Image and bitmap are no longer used!

As you can see at the end of the code its necessary to call GC.Collect() to release the memory.

So the question is, what is the right way to free the memory used by a WriteableBitmap object? Is GC.Collect() the only way?

Any help would be great.

PS. Sorry for my bad english.

private void buttonTest_Click(object sender, RoutedEventArgs e)
{
            Image image = new Image();
            image.Source = new BitmapImage(new Uri("BigImage"));

            WriteableBitmap bitmap = new WriteableBitmap(
                (BitmapSource)image.Source);

            bitmap.Lock();

            // Bitmap processing

            bitmap.Unlock();

            image = null;
            bitmap = null;

            GC.Collect();
}
3

3 Answers

3
votes

Are you running your test on Windows XP, using .Net 3.5 SP1? If so, then it is a known problem, that will be fixed in 4.0.

See http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5d88cdf1-e992-4ad4-8f56-b5dbf92dcf1c

1
votes

In general, memory should eventually be freed automatically as needed.

However, for that to happen, you need to be sure that the object is truly unused: No references to the object may exist anywhere, including references which "aren't used anymore". So, in particular, if you place your WriteableBitmap and original BitmapSource in variables of a long-lived class, they won't be released until the container is.

Also, WPF uses a retained GFX model: when you render, you're actually just storing instructions on how to render. The "instructions" on how to render a bitmap include a reference to the bitmap - so if you ever render a large bitmap, then for a while (at least as long as it's on screen - even if the version on screen is tiny) those images will be retained.

In practice; store references to these bitmaps only where they are needed, and if the context in which they live is long-lived (a long method call, or a method call generating a closure with a reference to the bitmaps, or a member of a long-lived class) then set them to null once they're no longer needed.

It is not necessary to manually free the memory; GC.Collect() should be superfluous. As a rule of thumb, only use GC.Collect during benchmarking to get an indication of memory consumption and/or to start with a clean slate. Overall performance is generally decreased by calls do GC.Collect().

0
votes

Forcing a GC without setting image and bitmap to null won't clean them up because they are still being referenced locally and are thus considered root references. This is nothing specifically to do with the WriteableBitmap and more a question of how GC works.

If you don't set them to null and don't force a garbage collection then they will be collected once the method exists and a GC occurs. That is recommended above forcing the collection yourself because you're probably hurting performance rather than helping it.