在C#中异步加载图像

时间:2012-06-12 18:14:17

标签: c# wpf multithreading image asynchronous

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

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

3 个答案:

答案 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?

如何为此

使用BindingList

How 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)

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

  • 创建一个实际执行图像加载工作的ImageProvider类
  • 让图像的viewmodel绑定到ItemViewModel中的ImageSource
  • 让这个ImageSource成为Lazy

    // //伪代码

    Lazy lazy = new Lazy(imageProvider.LoadImage(this.imagePath))

    //在ImageViewModel中......

    imageSource {get {return lazy.Value; }