Проблема с обновлением пользовательского интерфейса с помощью Dispatcher.Вызвать

#c# #wpf #ribbon-control

#c# #wpf #управление лентой

Вопрос:

Я работаю над приложением WPF на основе плагина. Плагины загружаются параллельно с использованием нескольких потоков. Один из плагинов — это плагин пользовательского интерфейса, который использует WPF RibbonWindow. Я пытаюсь добавить RibbonTab из плагина A в плагин пользовательского интерфейса.

Поскольку вызывающий поток не владеет RibbonWindow, я использую Dispatcher.Вызывается в RibbonWindow. К сожалению, код внутри делегата никогда не вызывается. Приложение по-прежнему реагирует, но вкладка не добавляется.

Могу ли я в любом случае получить доступ к потоку пользовательского интерфейса из другого плагина? Могу ли я создать поток, который можно поддерживать на протяжении всего моего приложения, чтобы я мог использовать этот поток для работы с RibbonWindow?

  System.Threading.ThreadStart start = delegate()
        {
            log.Debug(Thread.CurrentThread.ManagedThreadId);

            if (!this.Dispatcher.CheckAccess())
            {
                this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,  (ThreadStart)delegate() {
                    log.Debug(Thread.CurrentThread.ManagedThreadId);
                    ribbonRoot.Items.Add(myRibbonTab);
                });
            }
            else {
                log.Debug("We have access add directly.");
            }

        };

        new Thread(start).Start();
  

Пожалуйста, дайте мне знать, если вам нужна какая-либо дополнительная информация.

Спасибо.

Ответ №1:

Вам нужно Application.Current.Dispatcher вызвать его в потоке пользовательского интерфейса.

кстати: Почему вы ссылаетесь на ThreadStart? (не важно, просто любопытно)

Ответ №2:

Если вы просто хотите добавить вкладку ленты, вам не нужно запускать поток для этого (вы уже отправляете ее в поток пользовательского интерфейса), если только вы не хотите сделать в потоке больше. Даже тогда, возможно, было бы лучше использовать ThreadPool вместо создания нового потока. В любом случае, в подобных сценариях я обычно передаю Dispatcher из главного окна плагину через интерфейс плагина вместо прямого доступа к Application.Current.Dispatcher . Делает его более инкапсулированным, и у вас есть лучший контроль над ним в модульных тестах.

Комментарии:

1. Спасибо за ваш ответ. Теперь я получаю System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it. исключение. Я попытался создать ribbonwindow с помощью dispatcher, и это сделало приложение невосприимчивым. Пожалуйста, сообщите.

2. Мне пришлось создавать каждую ribbontab с помощью приложения. Текущий. Диспетчер и это решило мою проблему. Спасибо за помощь.