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

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

问题描述

我有一个生成一系列的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的项目,所以我认为有一个图片元素:

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

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

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

private BitmapImage _generatedImage;

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

我的视图模型还具有code创建后台线程:

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 调度,但我似乎无法拿出解决此问题的一个例子。请指教。

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线程上执行的操作委托。这使用了同步模式,备用 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的变,因此作为线程冻结的结果只读)。另一种选择是将图像加载到一个MemoryStream在后台线程,然后创建的BitmapImage在UI线程上与该流的BitmapImage的StreamSource的财产调度委托。

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.

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

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