我正在开发一个C#WPF应用程序,它可以加载大量图像并将其显示为缩略图。我想以多线程的方式做到这一点。因此,我尝试实现BackgroundWorker。
BackgroundWorker的DoWork()的代码:
string[] files = e.Argument as string[];
foreach (string file in files)
{
ImageModel image = new ImageModel();
image.FilePath = file;
_importWorker.ReportProgress(1, image);
_imageCollectionVM.Images.Add(image); // also tried this one in ReportProgress()
}
在我的XAML代码中,我绑定到ImageModel的BitmapImage属性。 (AsyncState = True没有帮助。)这里我得到这个错误:“DependencySource”和“DependencyObject”必须在同一个线程中。
<Image Source="{Binding BitmapImage}" />
如果我对此进行评论,图片似乎是导入的,但我无法访问它,例如通过在ListView中选择它。在其SelectionChanged中,它表示该对象由另一个线程拥有。
如何解决这些问题?提前谢谢!
答案 0 :(得分:2)
您必须将GUI的更新编组到主线程。基本上你只能从磁盘上多线程加载图像,但GUI的实际更新必须是单线程完成的。
有很多方法可以做到这一点,stackoverflow上的许多问题都解决了这个问题。这里有一些让你入门
Update UI from background Thread
Update BindingList<> from a background Thread?
Is it evil to update a pictureBox from a background C# thread?
如何为此
使用BindingListHow do you correctly update a databound datagridview from a background thread
答案 1 :(得分:1)
BackGround Worker对于大型任务来说是很好的imo,但如果它像你正在做的那样简单,我宁愿像这样做
以图片列表
开头List<Image> Images =new List<Image>();
然后运行此
Task.Factory.StartNew( () =>
{
string[] files = e.Argument as string[];
foreach (string file in files)
{
ImageModel image = new ImageModel();
image.FilePath = file;
// _importWorker.ReportProgress(1, image);
this.BeginInvoke( new Action(() =>
{
Images.Add(image);
}));
}
});
不保证我在该代码中拥有正确数量的括号。
答案 2 :(得分:0)
在类似情况下,我做了以下事情:
让这个ImageSource成为Lazy
// //伪代码
Lazy lazy = new Lazy(imageProvider.LoadImage(this.imagePath))
//在ImageViewModel中......
imageSource {get {return lazy.Value; }