在Image类中使用Task.Factory

时间:2014-01-25 03:27:17

标签: c# wpf task-parallel-library

我试图在不同的线程中加载图像,但图像永远不会更新。

public class MyImage : System.Windows.Controls.Image
{
  public MyImage()
  {
    this.Loaded += new RoutedEventHandler(MyImage_Loaded);
  }
  void MyImage_Loaded(object sender, RoutedEventArgs e)
  {
    //mypath=@"c:\test.jpg";
    var t = Task<ImageSource>.Factory.StartNew(() => GetImage(mypath));
    Source = t.Result;
  }

Error on Source

以下作品,但它是UI线程:

Source = GetImage(mypath);

我尝试使用BackgroundWorker,但结果是一样的。 没有MVVM可以这样做吗?

2 个答案:

答案 0 :(得分:3)

因为您在不同的线程上创建了ImageSource,所以您要在其上使用它

  

调用线程无法访问此对象,因为另一个线程拥有它

例外并解决您的问题,请致电ImageSource上的Freeze()。但是,即使您在不同的线程上加载图像,您的代码也会阻止UI线程,直到它准备就绪:

var t = Task<ImageSource>.Factory.StartNew(() => GetImage(mypath));
Source = t.Result; //this line blocks UI thread until Result is ready

如果您想避免将其更改为:

Task.Factory.StartNew(() =>
{
   var source = GetImage(mypath);
   source.Freeze();
   this.Dispatcher.Invoke(() => this.Source = source);
});

这应该在不同的线程上加载图像并在它准备就绪时更新Source而不阻塞UI线程

答案 1 :(得分:0)

尝试从GetImage(或从其结果)返回byte []或流,然后使用Dispatcher.Invoke调用UI线程上的帮助程序,该线程从byte []或流重新更新图像并更新MyImage的来源。

这是我工作的POC。您想检查它以正确处理流等。 (注意:disp是“发布”到UI的调度程序

Task.Factory.StartNew(() =>
                {
                    var result = GetImage();
                    var bitmap = new BitmapImage();
                    var stream = result;    
                    bitmap.BeginInit();
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.StreamSource = stream;

                    bitmap.EndInit();
                    bitmap.Freeze();
                    stream.Dispose();
                    disp.Invoke(new Action(()=> MyImage.Source = bitmap));
                });

GetImage()

    private MemoryStream GetImage()
    {
        System.Threading.Thread.Sleep(35000);
        var filePath = @"C:\temp\2013-01-08-235341.jpg";
        MemoryStream memoryStream = null;
        if (File.Exists(filePath))
        {
            memoryStream = new MemoryStream();

            byte[] fileBytes = File.ReadAllBytes(filePath);
            memoryStream.Write(fileBytes, 0, fileBytes.Length);
            memoryStream.Position = 0;
        }

        return memoryStream;
    }