WPF, BitmapFrames и перекрестный вопрос - PullRequest
0 голосов
/ 30 июня 2009

У меня есть некоторые BitmapFrames, созданные в потоке, отличном от основного потока пользовательского интерфейса; Через некоторое время после того, как они были созданы (и завершился их создательский поток), я пытаюсь использовать их в основном потоке в качестве источников для некоторых элементов управления изображениями.

НО я получаю это InvalidOperationException: вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку.

Нужна помощь, как я могу получить к ним доступ (и использовать) из основного потока?

Я не вижу, как я могу использовать Dispatcher.Invoke, так как второй поток завершен.

Заранее спасибо.

1 Ответ

2 голосов
/ 30 июня 2009

Есть две вещи, которые вы должны обеспечить:

  1. Остановите BitmapFrame, вызвав BitmapFrame.Freeze (). Это делает фрейм доступным только для чтения и делает его доступным для других потоков.

  2. Возможно, вы уже делаете это: чтобы сообщить потоку пользовательского интерфейса, что кадр готов, используйте 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();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...