2010-03-11 110 views
4

我有一些公平的圖像加載到我的WPF應用程序的ListBox中。最初我使用GDI來調整圖像大小(原稿佔用太多內存)。這很好,除了他們每張圖片需要大約400毫秒。不太好。因此,在尋找另一種解決方案時,我找到了一個使用TransformedBitmap(從BitmapSource繼承)的方法。這很好,我想,我可以使用它。除了我現在越來越內存泄漏的地方......異步加載BitmapSource圖像時發生內存泄漏

我異步加載使用一個BackgroundWorker,像這樣的圖片:

BitmapSource bs = ImageUtils.ResizeBitmapSource(ImageUtils.GetImageSource(photo.FullName)); 
       //BitmapSource bs = ImageUtils.GetImageSource(photo.FullName); 
       bs.Freeze(); 

       this.dispatcher.Invoke(new Action(() => { photo.Source = bs; })); 

GetImageSource只是得到從路徑的位圖,然後轉換成的BitmapSource。

下面是ResizeBitmapSource代碼片段:

const int thumbnailSize = 200; 
     int width; 
     int height; 

     if (bs.Width > bs.Height) 
     { 
      width = thumbnailSize; 
      height = (int)(bs.Height * thumbnailSize/bs.Width); 
     } 
     else 
     { 
      height = thumbnailSize; 
      width = (int)(bs.Width * thumbnailSize/bs.Height); 
     } 

     BitmapSource tbBitmap = new TransformedBitmap(bs, 
                  new ScaleTransform(width/bs.Width, 
                       height/bs.Height, 0, 0)); 

     return tbBitmap; 

該代碼基本上是從代碼: http://rongchaua.net/blog/c-wpf-fast-image-resize/

任何想法可能會導致泄漏?

編輯: 下面是GetImageSource的代碼,如要求

using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) 
      { 
       using (var bmp = Image.FromStream(stream, false, false)) 
       { 
        // Use WPF to resize 
        var bitmapSource = ConvertBitmapToBitmapSource(bmp); 
        bitmapSource = ResizeBitmapSource(bitmapSource); 
        return bitmapSource; 
       } 
      } 
+0

您是如何診斷泄漏的?你爲什麼認爲它在這個代碼中,而不是在例如GetImageSource()? – 2010-03-11 20:14:38

+0

我在WPF控件中使用的BitmapSource被正確調整大小,但看着進程使用的內存,它使用的是與完全大小的圖像相同的內存。因此,整個大小的BitmapSource不會被刪除。 編輯:因爲GetImageSource並沒有真正改變。如果我選擇用GDI調整大小,那很好。但是當我使用這個TransformedBitmap方法調整大小時,它不起作用。 – Harry 2010-03-11 20:17:27

+1

您可以嘗試打電話給手動GC以查看內存是否被釋放?如果不是的話,你最有可能在某個地方有一個引用,這個引用持有內存。 – 2010-03-11 21:05:04

回答

4

我想你誤解了TransformedBitmap的工作原理。它包含對源位圖的引用,並將其轉換到內存中。也許你可以將轉換後的位圖編碼到內存流中,然後馬上讀出來。我不確定這會有多快,但是你不會保留全尺寸的位圖。

我發現這個blog post返回一個WriteableBitmap作爲源TransformedBitmap。 WriteableBitmap會將像素數據複製到初始化程序中的內存緩衝區,因此它實際上不會保留對TransformedBitmap或全尺寸圖像的引用。

+0

好吧,我想我理解你。我會在早上嘗試,謝謝。 – Harry 2010-03-12 01:35:22

1

在猜測,從看你的代碼,你可能需要處理通過調用ImageUtils.GetImageSource(照片返回的位圖。全名)。

我在博客上也指出,作者已經添加了一個更新(3月11日)關於插入使用語句以防止內存泄漏。

+0

是的,這是基於我添加的評論。它似乎並沒有工作。不是說他的代碼是不正確的,但是有我的東西導致它去..錯誤... – Harry 2010-03-12 01:29:56