Почему Dispatcher.Invoke не запускает обновление пользовательского интерфейса? - PullRequest
2 голосов
/ 15 июня 2010

Я пытаюсь повторно использовать UserControl, а также позаимствовать некоторую логику, которая отслеживает прогресс.Я постараюсь упростить вещи.MyWindow.xaml включает в себя MyUserControl.MyUserControl имеет свой собственный индикатор прогресса (выполняется форматирование ..., копирование файлов ... и т. Д.), И я хотел бы отразить этот прогресс где-то в форме MyWindow.Но пользовательский элемент управления имеет некоторую логику, которую я не совсем понимаю.Я читал и читал, но я все еще не понимаю Диспетчер.Вот краткое изложение логики в пользовательском элементе управления, который обновляет прогресс.

this.Dispatcher.Invoke(DispatcherPriority.Input, (Action)(() =>
{
   DAProgressIndicator = InfiniteProgress.AddNewInstanceToControl(StatusGrid, new SolidColorBrush(new Color() { A = 170, R = 128, G = 128, B = 128 }), string.Empty);
                DAProgressIndicator.Message = MediaCardAdminRes.ActivatingCard;
                ActivateInProgress = true;
}));

Я подумал, что был бы умен и добавил бы в MyUserControl событие, которое будет вызываться в логике набора свойств ActivateInProgress.*

   public bool ActivateInProgress 
   {
      get
      {
         return _activateInProgress;
      }
      set
      {
         _activateInProgress = value;
         if (ActivateInProgressHandler != null)
         {
            ActivateInProgressHandler(value);
         }
      }
   }

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

private void SetActivation(bool activateInProgress)
{
   viewModel.ActivationInProgress = activateInProgress;
}

Однако окноиндикатор прогресса никогда не меняется.Итак, я убежден, что Dispatcher.Invoke делает что-то, чего я не понимаю.Если я помещаю окно сообщения в метод SetActivation, поток блокируется и индикатор прогресса окна обновляется.Я понимаю основные темы, но вся эта вещь о Диспетчере является новой для меня.Чего мне не хватает?

ОБНОВЛЕНИЕ: Кажется, сейчас работает.Оказывается, прогресс обновлялся так быстро, что его никогда не показывали на экране.Но я все еще хотел бы понять, почему был выполнен Dispatcher.Invoke (это был существующий код, который я не писал).Почему содержимое действия не выполняется в соответствии с остальной частью кода * .xaml.cs?

Ответы [ 2 ]

1 голос
/ 15 июня 2010

В вашем последнем абзаце дважды упоминаются темы, что повышает вероятность наличия одного или нескольких фоновых потоков. Но поскольку вы не упомянули, какие потоки существуют в приложении, как они создаются, как они взаимодействуют и т. Д., Я предполагаю, что на данный момент существует только один поток.

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

viewModel.ActivationInProgress = activateInProgress; 
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                       new Action(() => {}));

BeginInvoke заставляет все операции Dispatcher с приоритетом ввода завершаться до продолжения текущего потока.

0 голосов
/ 16 июня 2010

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

Возможно, попробуйте это:

DispatcherFrame _frame = new DispatcherFrame();
Dispatcher.PushFrame(_frame);

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

...