Memory Leaks in WPF based applications – Blog Update

We discovered few other potential memory leaks that WPF based application can encounter so I wanted to update my original Finding Memory Leaks in WPF-based applications blog and the sample in that blog with more info on these potential leaks.

Please review the blog updates and use the suggested workarounds to avoid such leaks in your WPF application (or upgrade to the .Net 3.5 Sp1 release when it becomes available).

These potential memory leaks could happen if you use the Image control when:

a) You use BitmapImage as the Image source and do not release the BitmapImage. E.g:

 static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute));
m_Image1 = new Image();
m_Image1.Source = bi1; 
//bi1.Freeze() //if you do not Freeze, your app will leak memory 
MyStackPanel.Children.Add(m_Image1);

b) You assign multiple BitmapImage as the Image source and do not release all of the BitmapImage you used (similar to (a)). This one introduced in .Net 3.5 ). E.g.:

 static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",
UriKind.RelativeOrAbsolute));
static BitmapImage bi2 = new BitmapImage(new Uri("Bitmap2.bmp",
UriKind.RelativeOrAbsolute));
bi2.Freeze();
m_Image1 = new Image();
//bi1.Freeze() //even though you are really using bi2 for Image Source, you also need to Freeze bi1 it to avoid leak 
m_Image1.Source = bi1;  // use un-frozen bitmap, which causes the leak
m_Image1.Source = bi2;  // use frozen bitmap
MyStackPanel.Children.Add(m_Image1);

c) You use BitmapImage that was downloaded from the Web as the Image source. E.g. below will leak:

 BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(@"https://www.somesite.com/some_image.png", UriKind.RelativeOrAbsolute);
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.None;
image.EndInit();                
m_Image1 = new Image();
m_Image1.Source = image;   
MyStackPanel.Children.Add(m_Image1);

See items (5), (6) and (7) in the blog for more detailed documentation, samples and workarounds.

Please note that these are fixed in the upcoming .Net 3.5 Sp1 release, so one potential workaround is to upgrade.