Releasing BitmapImages used as Image control Source (memory problem)
I have a simple WPF window with an Image control and a Slider control under it. When the user moves the slider, I'm l开发者_开发百科oading and setting various images as Source of the Image-control. I got quite a few images, varying in size up to a 200 KB, but when I move that slider back and fourth, the program starts to eat quite a lot of memory. Hundreds and hundreds of megs of memory. Most of it gets garbage collected eventyally, but not all.
Maybe WPF isn't the way to go or should I force a G/C? I've tried loading the image as Bitmap and getting the bitmap source with Imaging.CreateBitmapSourceFromHBitmap()
and Win32-api's to delete and dispose and so on, but I'm just making things worse :)
I guess I should try to grab the existing image source and release it somehow before loading and assigning a new one.
Any ideas?
EDIT
I'm adding some sample code that worked fine and seems to keep the memory low and fine:
private Image _lastImage;
// Event when user moves the slider control, load image using the filname in
// the _images[] array which contains hundreds of images
private void SliderChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_lastImage != null)
_lastImage.Dispose();
var image = Image.FromFile(_images[(int)ImageSlider.Value]);
Snapshot.Source = ImageToBitmapImage(image);
_lastImage = image;
}
private static ImageSource ImageToBitmapImage(Image image)
{
BitmapImage bitmapImage;
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Jpeg);
bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(ms.ToArray());
bitmapImage.EndInit();
}
return bitmapImage;
}
Forcing a GC collection is indeed horrible. Instead call the .Dispose()
method of the Bitmap
object, that's what it's there for!
- The method you are using (Imaging.CreateBitmapSourceFromHBitmap()) is unmanaged and probably requires that you manually .Dispose() of it.
- WPF allows you to load a bitmap via a given URI : see http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.aspx
- The GC will take care of collecting any managed objects you have (by using BitmapImage for example).
- You are probably loading too many images to memory. the source images accumulate memory pretty fast (1024x786 image at 32bit color takes up around 3mb of ram). The GC has to work very hard to clean them up. You could reduce the size of the image after loading (scale it down) and use up less memory
- Finally, the GC does not guarantee that all memory will be released after the GC cycle. It promises "best effort". although typically calling GC.Collect(0); will force a full GC cycle and release almost everything that can be released.
精彩评论