Есть две вещи, которые вы должны обеспечить:
Остановите BitmapFrame, вызвав BitmapFrame.Freeze (). Это делает фрейм доступным только для чтения и делает его доступным для других потоков.
Возможно, вы уже делаете это: чтобы сообщить потоку пользовательского интерфейса, что кадр готов, используйте Dispatcher.Invoke вместо установки свойств или непосредственного вызова методов объектов пользовательского интерфейса.
Чтобы ответить на вопрос Теодора, замораживание может завершиться неудачей, если 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();
}
}
}