Диспетчер WPF { "вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток".}
Сначала мне нужно сказать, что я noob с WPF и С#.
Приложение: Создайте изображение Мандельброта (GUI)
Мой диспетчер отлично работает в этом случае:
private void progressBarRefresh(){
while ((con.Progress) < 99)
{
progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
{
progressBar1.Value = con.Progress;
}
));
}
}
Я получаю сообщение (заголовок), когда tring делает это с помощью приведенного ниже кода:
bmp = BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, stride);
this.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
{
img.Source = bmp;
ViewBox.Child = img; //vllt am schluss
}
));
Я попытаюсь объяснить, как работает моя программа.
Я создал новую тему (потому что GUI не отвечает) для вычисления пикселей и цветов. В этой теме (методе) я использую диспетчер для обновления моего изображения в ViewBox после того, как вычисления будут готовы.
Когда я не ставил вычисления в отдельный поток, я могу обновить или создать свое изображение.
Ответы
Ответ 1
На всякий случай, если вы хотите, чтобы объект был разделен между разными потоками, всегда создавайте этот объект в потоке пользовательского интерфейса. Позже, когда вы хотите получить доступ к объекту, вы можете проверить, есть ли у вас доступ к объекту. Если у вас нет доступа, повторно вызовите функцию с доступом к потоку пользовательского интерфейса. пример кода ниже:
private void YourMethod()
{
if (Application.Current.Dispatcher.CheckAccess())
{
// do whatever you want to do with shared object.
}
else
{
//Other wise re-invoke the method with UI thread access
Application.Current.Dispatcher.Invoke(new System.Action(() => YourMethod()));
}
}
Ответ 2
MSDN говорит: "Замороженный Freezable может быть разделен между потоками".
Возможно, этот поток поможет: http://social.msdn.microsoft.com/Forums/en-US/windowswic/thread/9223743a-e9ae-4301-b8a4-96dc2335b686
Ответ 3
Вы создаете растровое изображение (bmp
) в потоке рабочего (?), а затем передаете его в поток пользовательского интерфейса - это не работает.
Вам нужно создать изображение в потоке пользовательского интерфейса. Вероятно, вам понадобится какой-то способ ссылки на изображение, которое вы хотите отобразить, и передать эту информацию в пользовательский интерфейс.
Ответ 4
Вы также можете использовать механизм массового обслуживания для передачи сообщений между потоками. В конце концов, это то, как работает архитектура Windows. Это то, что делает диспетчер. Вы передаете ссылку в делегат, который не принадлежит потоку WPF.
Итак, у вас есть основная идея, но вам нужно передать битмап в другой поток, используя Action<T>(T object)
или в вашем случае:
Dispatcher.Invoke(DispatcherPriority.Send, new Action<Bitmap>(delegate(Bitmap img) {
do things here...
}), bmp);
Ответ 5
Когда вы получаете Dispatcher
, вы получаете разные для каждого потока.
this.Dispatcher
может дать вам еще один диспетчер, а не пользовательский интерфейс, поэтому вы получите эту ошибку.
Попробуйте вместо этого использовать Application.Current.Dispatcher
, это всегда будет возвращать диспетчер потока пользовательского интерфейса.
Такая же ошибка может произойти, если вы используете Dispatcher.CurrentDispatcher
из другого потока, конечно.