4

我正在开发一个 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 中,它说该对象由另一个线程拥有。

我该如何解决这些问题?提前致谢!

4

3 回答 3

2

您必须将 GUI 的更新编组到主线程。基本上你只能多线程从磁盘加载图像,但 GUI 的实际更新必须单线程完成。

有很多方法可以做到这一点,stackoverflow 上的许多问题都解决了这个问题。这里有一些可以帮助您入门

从后台线程更新 UI

从后台线程更新 BindingList<>?

从后台 C# 线程更新图片框是邪恶的吗?

如何为此使用 BindingList

如何从后台线程正确更新数据绑定 datagridview

于 2012-06-12T18:17:42.853 回答
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);
         }));
     }
 });

不能保证我在该代码中有正确数量的括号。

于 2012-06-12T18:22:15.053 回答
0

在类似的情况下,我做了以下事情:

  • 创建一个实际执行图像加载工作的 ImageProvider 类
  • 让图像的视图模型绑定到我的 ItemViewModel 中的 ImageSource
  • 让这个 ImageSource 变得懒惰

    // // 这里的伪代码

    懒惰 = new Lazy(imageProvider.LoadImage(this.imagePath))

    // 在 ImageViewModel ...

    imageSource { 获取 { 返回lazy.Value; } }

于 2012-06-12T18:22:20.340 回答