如何在后台加载图像?

kev*_*aub 3 c# wpf delegates image

我正在尝试在后台加载图像,然后更新UI.我整天都在玩这个,我不知道我错过了什么.我一直收到以下错误:

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

我已经在示例后跟随示例,但我似乎无法找到答案.我还包含了在另一个BeginInvoke中触摸UI的代码.

更新3:故事的寓意.ImageSource对于访问不是线程安全的.

更新2:这必须是一个简单的解决方案:).我尝试了克隆,但这并没有带来成功,但我确实得到了一个不同的错误:"调用目标引发了异常."

更新1:我尝试了BackgroundWorker,但我仍然得到相同的错误,但它发生在brush.ImageSource.Height上.我是否正确发信号通知UI?有什么建议?

这是我的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>
Run Code Online (Sandbox Code Playgroud)

以下是一些背后的代码:

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;
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

ben*_*wey 11

我倾向于使用它ThreadPool.QueueUserWorkItem来加载图像,然后当操作完成时,我使用线程安全Dispatcher对象回调UI线程.图像源不是线程安全的,你将不得不使用类似的东西JpegBitmapDecoder,还有一个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;
}
Run Code Online (Sandbox Code Playgroud)