2015-06-14 69 views
0

我試圖顯示(在具有自定義DataTemplate的ListBox中)從多頁Tiff圖像中提取的一系列BitmapSource框架(縮略圖)。當我在UI線程上處理tiff,並直接將圖像添加到列表框的項目集合或將它們添加到綁定的ObservableCollection時,它們在列表中顯示正常。然而,試圖異步加載每個縮略圖(或者使用的BackgroundWorker或使用異步任務)的時候,我看到的行爲我不能工作了:如預期異步加載時不出現在WPF窗體上的圖像

  • 第一縮略圖加載
  • 下,和所有後續縮略圖獲得列表中的項目(我看到了邊框),但所有顯示的都是空白圖像。它顯示正確的項目數量,但在第一個之後沒有圖像。

我玩過試圖凍結縮略圖(不行),嘗試將它們發送回UI線程並通過工作人員的ReportProgress將它們添加到集合中(但不行),但我可以似乎沒有讓他們表現出來。

工作UI線程(其中SyncImages是綁定到我的列表框一個ObservableCollection和OnPropertyChanged處理通知事件):

private void LoadSynchronous() 
{ 
    Stream imageStreamSource = new FileStream(ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read); 
    var decoder = BitmapDecoder.Create(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, 
     BitmapCacheOption.Default); 

    foreach (var frame in decoder.Frames) 
    { 
     //frame.Freeze(); //Tried this but no effect. 
     SyncImages.Add(frame); 
    } 

    OnPropertyChanged("SyncImages"); 
} 

不工作(這個例子中直接添加幀到列表中,但我我也嘗試通過綁定結果沒有任何區別):

private void LoadAsync(object sender, DoWorkEventArgs e) 
{ 
    Stream imageStreamSource = new FileStream(ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read); 
    var decoder = BitmapDecoder.Create(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, 
     BitmapCacheOption.Default); 

    foreach (var frame in decoder.Frames) 
    { 
     // frame.Freeze(); 
     (sender as BackgroundWorker).ReportProgress(0, frame); 
    } 

    OnPropertyChanged("AsyncImages"); 
} 

private void ReportAsyncProgress(object send, ProgressChangedEventArgs e) 
    { 
     var frame = (BitmapSource) e.UserState; 
     LbAsynchronous.Items.Add(frame); 
    } 

希望有人可以對這裏發生的事情有所瞭解。我知道代碼可以提取框架,所以即使在異步示例中它們也必須加載,但看起來好像UI線程無法訪問保存圖像數據以在窗體上顯示它們的源的屬性(這就是爲什麼我試圖凍結)。

任何想法,將不勝感激!

示例圖像:從他原來的問題評論http://i.imgur.com/75wMkmS.png

+0

不知道爲什麼凍結不能正常工作,你可以看一些其他的建議在這裏:http://stackoverflow.com/questions/3034902/怎麼做 - 你從背景線程到線程 - UI-thread-in-wpf – vesan

+0

感謝您的鏈接 - 我一直在檢查這些建議,看看是否有任何結果它。我附上了一張圖片,希望能引發一個推薦:http://i.imgur.com/75wMkmS.png左邊是UI線程處理結果,右邊是BackgroundWorker/async版本。 –

+2

你正在關閉FileStream嗎?爲了確保立即加載所有幀,並且可以在創建BitmapFrame後立即關閉流,應該設置「BitmapCacheOption.OnLoad」而不是「Default」。 – Clemens

回答

2

@Clemens答案提供的解決方案。確保文件流正在被負責任地關閉,並且現在將BitmapCacheOption更改爲OnLoad將顯示異步加載中的每個映像。

異步加載的最終代碼看起來像:

private void LoadAsync(object sender, DoWorkEventArgs e) 
    { 
     BitmapDecoder decoder; 

     using (Stream imageStreamSource = new FileStream(ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      decoder = BitmapDecoder.Create(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, 
       BitmapCacheOption.OnLoad); 

     } 

     foreach (var frame in decoder.Frames) 
     { 
      frame.Freeze(); 
      (sender as BackgroundWorker).ReportProgress(0, frame); 
     } 
    } 

    private void UpdateAsync(object send, ProgressChangedEventArgs e) 
    { 
      SyncImages.Add((BitmapSource)e.UserState); 
      OnPropertyChanged("SyncImages"); 

    }