WPF Dispatcher {"Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку."} - PullRequest
15 голосов
/ 06 июня 2010

сначала я должен сказать, что я нуб с WPF и C #. Приложение: создание образа Мандельброта (GUI) Мой диспетчер отлично работает в этом случае:

  private void progressBarRefresh(){

       while ((con.Progress) < 99)
       {
           progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
                {
                    progressBar1.Value = con.Progress;
                }
              ));
       }
  }

Я получаю сообщение (название), когда пытаюсь сделать это с кодом ниже:

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 не отвечает) для расчета пикселей и цветов. В этой теме (метод) я использую Dispatcher для обновления моего изображения во ViewBox после завершения расчетов.

Когда я не помещаю вычисления в отдельный поток, тогда я могу обновить или построить свой образ.

Ответы [ 5 ]

25 голосов
/ 05 декабря 2012

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

    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()));
        }
    }
7 голосов
/ 06 июня 2010

MSDN говорит: «Замороженный Freezable может быть разделен между потоками.»

Может быть, эта тема поможет: http://social.msdn.microsoft.com/Forums/en-US/windowswic/thread/9223743a-e9ae-4301-b8a4-96dc2335b686

3 голосов
/ 29 января 2013

Когда вы получаете Dispatcher, вы получаете разные для каждой другой нити.

this.Dispatcher может дать вам другой Диспетчер, а не пользовательский интерфейс, поэтому вы получите эту ошибку.

Попробуйте использовать Application.Current.Dispatcher, вместо этого всегда будет возвращаться Dispatcher потока пользовательского интерфейса.

Та же ошибка может произойти, если вы, конечно, используете Dispatcher.CurrentDispatcher из другого потока.

2 голосов
/ 06 июня 2010

Вы также можете использовать механизм очереди для передачи сообщений между потоками. В конце концов, так работает архитектура Windows. Это то, что делает диспетчер. Вы передаете ссылку в делегат, который не принадлежит потоку WPF.

Так что да, у вас есть основная идея, но вам нужно на самом деле передать растровое изображение в другой поток, используя Action<T>(T object), или в вашем случае:

Dispatcher.Invoke(DispatcherPriority.Send, new Action<Bitmap>(delegate(Bitmap img) {
    do things here...
}), bmp);
2 голосов
/ 06 июня 2010

Вы создаете растровое изображение (bmp) в своем рабочем (?) Потоке, а затем передаете его в поток пользовательского интерфейса - это то, что не работает.

Вам необходимо создать изображение в потоке пользовательского интерфейса. Вам, вероятно, понадобится какой-то способ указать, какое изображение вы хотите отобразить, и передать эту информацию в пользовательский интерфейс.

...