释放用作图像控制源的BitmapImages(内存问题)

时间:2011-04-03 15:53:02

标签: wpf

我有一个简单的WPF窗口,下面有一个Image控件和一个Slider控件。当用户移动滑块时,我正在加载并将各种图像设置为图像控件的源。我有相当多的图像,大小不一,最大可达200​​ KB,但是当我将滑块移回第四个时,程序开始吃掉相当多的内存。数以百计的记忆。其中大部分都是垃圾收集,但不是全部。

也许WPF不是要走的路,或者我应该强制使用G / C?我已经尝试将图像加载为Bitmap并使用Imaging.CreateBitmapSourceFromHBitmap()和Win32-api获取位图源来删除和处理等等,但我只是让事情变得更糟:)

我想我应该尝试抓住现有的图像源并在加载和分配新图像之前以某种方式释放它。

有什么想法吗?

修改

我正在添加一些工作正常的示例代码,似乎可以保持内存的低位和精细:

    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;
    }

3 个答案:

答案 0 :(得分:0)

强制进行GC收集确实非常糟糕。而是调用.Dispose()对象的Bitmap方法,这就是它的用途!

答案 1 :(得分:0)

  1. 您正在使用的方法(Imaging.CreateBitmapSourceFromHBitmap())是非托管的,可能需要您手动.Dispose()。
  2. WPF允许您通过给定的URI加载位图:请参阅http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.aspx
  3. GC将负责收集您拥有的任何托管对象(例如,使用BitmapImage)。
  4. 您可能正在将太多图像加载到内存中。源图像非常快速地累积内存(32位色的1024x786图像占用大约3mb的内存)。 GC必须非常努力地清理它们。您可以在加载(缩小图像)并减少使用内存后缩小图像大小
  5. 最后,GC不保证在GC循环后释放所有内存。 它承诺“尽力而为”。虽然通常调用GC.Collect(0);将强制完整的GC循环并释放几乎所有可以释放的东西。

答案 2 :(得分:0)

您是否在.NET 4中尝试过the new BitmapCache class?它可能会解决您的问题。