我在主UI线程以外的线程上创建了一些BitmapFrame; 在创建它们之后的某个时间(以及它们的创建者线程完成),我试图在主线程中使用它们作为某些Image控件的源代码。
但是我得到了这个InvalidOperationException
:调用线程无法访问该对象,因为另一个线程拥有它。
需要一些帮助,如何从主线程中访问(和使用)它们?
自第二个线程完成以来,我没有看到如何使用Dispatcher.Invoke。
提前谢谢。
答案 0 :(得分:2)
您必须确保两件事:
通过调用BitmapFrame.Freeze()来冻结BitmapFrame。这会将帧变为只读,并使其可供其他线程使用。
您可能已经这样做了:要让UI线程知道框架已准备就绪,请使用Dispatcher.Invoke,而不是直接设置属性或调用UI对象的方法。
要回答Teodor的问题,如果仍在更改BitmapFrame,冻结可能会失败。当您使用BitmapFrame.Create(Uri)时,似乎会发生这种情况。以下代码似乎通过使用解码器来避免此问题。如果您以不同方式创建BitmapFrame,一般规则是您必须让它在冻结之前完成初始化,下载,解码或以其他方式更改。断开所有绑定。
Window1.xaml
<Window x:Class="BitmapFrameDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Image Name="image"/>
</Grid>
</Window>
Window1.xaml.cs
using System;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace BitmapFrameDemo {
public partial class Window1 : Window {
private Thread thread = null;
private Dispatcher dispatcher = null;
private void ThreadMain() {
PngBitmapDecoder decoder = new PngBitmapDecoder(
new Uri("http://stackoverflow.com/content/img/so/logo.png"),
BitmapCreateOptions.None,
BitmapCacheOption.Default);
BitmapFrame frame = decoder.Frames[0];
BitmapFrame frozen = (BitmapFrame) frame.GetAsFrozen();
dispatcher.Invoke(
new Action(() => { image.Source = frozen; }),
new object[] { });
}
public Window1() {
InitializeComponent();
dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(new ThreadStart(this.ThreadMain));
thread.Start();
}
}
}