C# 异步加载时WPF表单上不显示的图像
我正在尝试显示(在带有自定义数据模板的列表框中)从多页tiff图像中提取的一系列位图源帧(缩略图)。当我在UI线程上处理tiff时,或者直接将图像添加到listbox的项集合,或者将它们添加到绑定的ObservableCollection,它们在列表中显示良好。但是,当尝试异步加载每个缩略图时(使用BackgroundWorker或使用异步任务),我会看到无法解决的行为:C# 异步加载时WPF表单上不显示的图像,c#,wpf,multithreading,listbox,backgroundworker,C#,Wpf,Multithreading,Listbox,Backgroundworker,我正在尝试显示(在带有自定义数据模板的列表框中)从多页tiff图像中提取的一系列位图源帧(缩略图)。当我在UI线程上处理tiff时,或者直接将图像添加到listbox的项集合,或者将它们添加到绑定的ObservableCollection,它们在列表中显示良好。但是,当尝试异步加载每个缩略图时(使用BackgroundWorker或使用异步任务),我会看到无法解决的行为: 第一个缩略图按预期加载 下一个和所有后续缩略图都会获取列表中的项目(我看到边框),但显示的只是一个空白图像。它显示正确的项
- 第一个缩略图按预期加载
- 下一个和所有后续缩略图都会获取列表中的项目(我看到边框),但显示的只是一个空白图像。它显示正确的项目数,但第一个项目后没有图像
示例图片:@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");
}
不知道为什么冻结不起作用,你可以在这里看一些其他的建议:谢谢你的链接-我一直在看这些建议,看看是否有什么解决办法。我附上了一张图片,希望它能引发一个建议:左边是UI线程处理结果,右边是BackgroundWorker/async版本。您是否在任何地方关闭文件流?为了确保立即加载所有帧,并且在创建BitmapFrames后可以立即关闭流,您应该设置
BitmapCacheOption.OnLoad
而不是Default
@Clemens,您关于BitmapCacheOption.OnLoad
的建议成功了!谢谢你的帮助!
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);
}
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");
}