如何将 BitmapImage 从后台线程传递到 WPF 中的 UI 线程? [英] How do you pass a BitmapImage from a background thread to the UI thread in WPF?

查看:18
本文介绍了如何将 BitmapImage 从后台线程传递到 WPF 中的 UI 线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个后台线程,它生成一系列 BitmapImage 对象.每次后台线程完成生成位图时,我想向用户显示此位图.问题是弄清楚如何将 BitmapImage 从后台线程传递到 UI 线程.

I have a background thread that generates a series of BitmapImage objects. Each time the background thread finishes generating a bitmap, I would like to show this bitmap to the user. The problem is figuring out how to pass the BitmapImage from the background thread to the UI thread.

这是一个 MVVM 项目,所以我的视图有一个 Image 元素:

This is an MVVM project, so my view has an Image element:

<Image Source="{Binding GeneratedImage}" />

我的视图模型有一个属性 GeneratedImage:

My view-model has a property GeneratedImage:

private BitmapImage _generatedImage;

public BitmapImage GeneratedImage
{
    get { return _generatedImage; }
    set
    {
        if (value == _generatedImage) return;
        _generatedImage= value;
        RaisePropertyChanged("GeneratedImage");
    }
}

我的视图模型也有创建后台线程的代码:

My view-model also has the code that creates the background thread:

public void InitiateGenerateImages(List<Coordinate> coordinates)
{
    ThreadStart generatorThreadStarter = delegate { GenerateImages(coordinates); };
    var generatorThread = new Thread(generatorThreadStarter);
    generatorThread.ApartmentState = ApartmentState.STA;
    generatorThread.IsBackground = true;
    generatorThread.Start();
}

private void GenerateImages(List<Coordinate> coordinates)
{
    foreach (var coordinate in coordinates)
    {
        var backgroundThreadImage = GenerateImage(coordinate);
        // I'm stuck here...how do I pass this to the UI thread?
    }
}

我想以某种方式将 backgroundThreadImage 传递给 UI 线程,在那里它将变成 uiThreadImage,然后设置 GeneratedImage = uiThreadImage视图可以更新.我查看了一些处理 WPF Dispatcher 的示例,但我似乎无法想出解决此问题的示例.请指教.

I'd like to somehow pass backgroundThreadImage to the UI thread, where it will become uiThreadImage, then set GeneratedImage = uiThreadImage so the view can update. I've looked at some examples dealing with the WPF Dispatcher, but I can't seem to come up with an example that addresses this issue. Please advise.

推荐答案

以下使用调度器在 UI 线程上执行 Action 委托.这使用同步模型,替代的 Dispatcher.BeginInvoke 将执行委托异步.

The following uses the dispatcher to execute an Action delegate on the UI thread. This uses a synchronous model, the alternate Dispatcher.BeginInvoke will execute the delegate asynchronously.

var backgroundThreadImage = GenerateImage(coordinate);

GeneratedImage.Dispatcher.Invoke(
        DispatcherPriority.Normal,
        new Action(() =>
            {
                GeneratedImage = backgroundThreadImage;
            }));

更新正如评论中所讨论的,由于 BitmapImage 不是在 UI 线程上创建的,因此仅靠上述方法是行不通的.如果您在创建图像后无意修改图像,您可以使用 冻结它Freezable.Freeze 然后分配给调度程序委托中的 GeneratedImage(BitmapImage 变为只读,因此作为 Freeze 的结果是线程安全的).另一种选择是将图像加载到后台线程上的 MemoryStream 中,然后使用该流和 BitmapImage 的 StreamSource 属性在调度程序委托中的 UI 线程上创建 BitmapImage.

UPDATE As discussed in the comments, the above alone will not work as the BitmapImage is not being created on the UI thread. If you have no intention of modifying the image once you have created it you can freeze it using Freezable.Freeze and then assign to GeneratedImage in the dispatcher delegate (the BitmapImage becomes read-only and thus threadsafe as a result of the Freeze). The other option would be to load the image into a MemoryStream on the background thread and then create the BitmapImage on the UI thread in the dispatcher delegate with that stream and the StreamSource property of BitmapImage.

这篇关于如何将 BitmapImage 从后台线程传递到 WPF 中的 UI 线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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