2011-04-03 67 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循環,並釋放幾乎所有可以釋放的東西。