我正在尝试显示(在带有自定义DataTemplate的ListBox中)从多页tiff图像中提取的一系列BitmapSource帧(缩略图)。当我在UI线程上处理tiff,并直接将图像添加到列表框的项集合或将它们添加到绑定的ObservableCollection时,它们在列表中显示正常。但是,当尝试异步加载每个缩略图时(使用BackgroundWorker或使用异步任务),我看到我无法解决的行为:
我试图冻结缩略图(没有好处),尝试将它们发送回UI线程,然后通过worker的ReportProgress将它们添加到集合中(没有好处),但我似乎无法忍受让他们展示。
使用UI线程(其中SyncImages是绑定到ListBox的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线程似乎无法访问保存图像数据的源的属性以在表单上显示它们(这就是我尝试冻结的原因)。
任何想法都将不胜感激!
答案 0 :(得分:2)
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");
}