代码之家  ›  专栏  ›  技术社区  ›  Fermin

WPF/BackgroundWorker和BitmapSource问题

  •  5
  • Fermin  · 技术社区  · 15 年前

    我是WPF的初学者,尝试一个家庭项目来熟悉这项技术。我有一个简单的表单,用户在其中选择一个图像文件,然后显示exif数据以及图像的缩略图。这很好,但是当我选择一个原始图像文件(~9MB)时,在拇指加载时可能会有轻微的延迟,所以我认为我可以使用BackgroundWorker来解码图像,用户可以查看exif数据,然后当图像被解码后,就会显示出来。

    BitmapSource对象在BackgroundWorkers DoWork方法中声明:

    worker.DoWork += delegate(object s, DoWorkEventArgs args)
    {
        string filePath = args.Argument as string;
    
        BitmapDecoder bmpDecoder = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.None);
        BitmapSource bmpSource = bmpDecoder.Frames[0];
        bmpSource.Freeze(); //As suggested by Paul Betts
    
        args.Result = bmpSource;
    };
    

    我遇到的问题是,当我尝试在RunWorkerCompleted方法中设置图像控件的源代码时,我收到一个错误,因为该对象属于另一个线程。

    worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
    {
        imgThumb.Source = args.Result as BitmapSource;
    };
    

    我试着用 imgThumb.Dispatcher.BeginInvoke() 方法来设置源,但这也不起作用,我想是因为它是 args.Result 它属于另一个线程,而不是 imgThumb 是吗?我怎么才能绕过这个?

    可能是我对调度员的编码有误(下面是从内存中删除的内容)。

    imgThumb.Dispatcher.Invoke(new Action<BitmapSource>(
        delegate(BitmapSource src)
        {
            imgThumb.Source = src;
        }
    ), bmpSource);
    

    欢迎提出任何建议或想法。

    更新

    更改了我的DoWork方法以使用BitmapCreateOptions.none而不是.delayCreation,但现在我在加载原始文件(Canon.cr2文件是我迄今为止测试过的所有文件)时遇到以下错误,该代码对JPG的工作正常。这是否是我安装的Canon编解码器允许我显示原始文件的问题?

    应用程序调用了接口 那是为了另一个 线程。(来自hresult的异常: 0x8001010E(rpc_e_错误_线程)

    2 回复  |  直到 13 年前
        1
  •  8
  •   Ana Betts    15 年前

    在BitmapSource上调用freeze(),您将不会遇到此问题(冻结消除了线程限制,但使对象不可变)

        2
  •  2
  •   bohdan_trotsenko    13 年前

    我有一个样本问题,很幸运能解决它。

    简短回答:总结 WriteableBitmap . 那是以一点代价来的,你。

    Long answer .