2015-06-14 72 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"); 

    }