2011-04-03 68 views
3

我有一个简单的WPF窗口,下面有一个Image控件和一个Slider控件。当用户移动滑块时,我正在加载和设置各种图像作为图像控件的来源。我获得了不少图像,大小可以达到200 KB,但是当我将该滑块移回第四个时,程序开始消耗相当多的内存。成百上千的记忆。它大部分都会通过垃圾收集,但不是全部。释放用作图像控件的BitmapImages源(内存问题)

也许WPF是不是要走的路还是应该强制一个G/C?我试图加载图像作为位图和获取位图源与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; 
    } 

回答

0

强制GC集合确实是太可怕了。而是调用Bitmap对象的.Dispose()方法,这就是它的用途!

+0

我试过了,但它没有帮助。我很确定我正在加载并以某种方式分配源错误:( – 2011-04-03 16:24:46

+0

我改变了我的代码,有点像我从文件创建位图源的方式,并确保我放置了前面的位图,如您所说(和因为我早些时候尝试过,但是失败了),请注意它现在可以工作了。将更新原始问题的示例代码。 – 2011-04-04 19:21:47

+0

@Jonah,如果它不为null,则可以将'Snapshot.Source'强制转换为'Image'分配新图像如果您没有对图像进行如此多的引用,那么GC本身就会自行完成,而无需额外的复杂操作。 – Blindy 2011-04-04 22:34:15

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循环,并释放几乎所有可以释放的东西。