如何在后台加载图像? [英] How do I load images in the background?

查看:176
本文介绍了如何在后台加载图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在后台加载图片,然后更新UI。我一整天都在玩,我不知道我失踪了什么。我收到以下错误:

I am trying to load an image in the background and then update the UI. I have been playing with this all day and I don't know what I am missing. I keep getting the following error:


调用线程无法访问此对象,因为不同的线程拥有它。

"The calling thread cannot access this object because a different thread owns it."

我以下例子中的例子搜到了,但我似乎找不到答案。我还在另一个BeginInvoke中包装了触摸UI的代码。

I've hunted around following example after example, but I cannot seem to find an answer. I also wrapped the code that is touching the UI in another BeginInvoke.

更新3:故事的道德。 ImageSource不是线程安全的访问。

Update 3: The moral of the story. ImageSource is not thread safe for access.

更新2:这必须是一个简单的解决方案:)。我试过克隆,但是并没有取得成功,但是我确实遇到了一个不同的错误:调用目标抛出异常。

Update 2: This has got to be a simple solution :). I tried the cloning, but that didn't result in success, but I did get a different error: "Exception has been thrown by the target of an invocation."

更新1:我尝试了BackgroundWorker,但我仍然收到相同的错误,但它正在刷.ImageSource.Height。我是否正确表示UI?任何建议?

Update 1: I tried the BackgroundWorker, but I am still getting the same error, but it is occurring on the brush.ImageSource.Height. Am I signaling the UI correctly? Any suggestions?

这是我的XAML:

<Window x:Class="Slideshow.Show"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DockPanel>
        <Canvas Background="Black" Name="canvas">
            <Viewbox Name="background" Stretch="Uniform">
                <Rectangle name="background" />
            </Viewbox>
        </Canvas>
    </DockPanel>
</Window>

以下是一些代码:

namespace Slideshow
{
    public class Show 
    {
        public Show()
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            BitmapSource bitmap = e.Result as BitmapSource;

            if (bitmap != null)
            {
                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal 
                    (ThreadStart)delegate()
                {
                    Image image = new Image();
                    image.Source = bitmap;
                    background.Child = image;
                 });
            }
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BitmapSource bitmapSource = CreateBrush(GetRandomFile());
            e.Result = bitmapSource;
         }
    }
}


推荐答案

我倾向于使用 ThreadPool.QueueUserWorkItem 来加载图像,然后当操作完成时,我使用线程安全的 Dispatcher 对象。图像源不是线程安全的,您将不得不使用类似于 JpegBitmapDecoder 的内容,还有一个 PngBitmapDecoder

What I tend to use the ThreadPool.QueueUserWorkItem to load the image, then when the operation completes I call back to the UI thread using the thread-safe Dispatcher object. The image source is not thread safe, you will have to use something like the JpegBitmapDecoder, there is also a PngBitmapDecoder.

例如:

public Window()
{
    InitializeComponent();

    ThreadPool.QueueUserWorkItem(LoadImage,
         "http://z.about.com/d/animatedtv/1/0/1/m/simp2006_HomerArmsCrossed_f.jpg");
}

public void LoadImage(object uri)
{
    var decoder = new JpegBitmapDecoder(new Uri(uri.ToString()), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
    decoder.Frames[0].Freeze();
    this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), decoder.Frames[0]);
}

public void SetImage(ImageSource source)
{
    this.BackgroundImage.Source = source;
}

这篇关于如何在后台加载图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆