为什么Dispatcher.Invoke不会触发UI更新?

时间:2010-06-15 00:14:56

标签: c# wpf dispatcher

我正在尝试重用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);
         }
      }
   }

我将MyWindow构造函数中的ActivateInProgressHandler设置为以下方法,该方法设置用于窗口自身进度指示器的视图模型属性。

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

但是,窗口的进度指示器永远不会改变。所以,我确信Dispatcher.Invoke正在做一些我不理解的事情。如果我在SetActivation方法中放置一个消息框,则更新线程块和窗口的进度指示器。我理解基本线程,但整个Dispatcher对我来说都是新的。我错过了什么?

更新:现在似乎正在运作。事实证明,进展正在快速更新,以至于它从未在屏幕上显示过。但是,我仍然想了解为什么Dispatcher.Invoke已经完成(这是我没有写的现有代码)。为什么动作内容不与* .xaml.cs代码的其余部分一致?

2 个答案:

答案 0 :(得分:1)

你的最后一段提到了两次线程,这就提出了有一个或多个后台线程的可能性。但是既然你没有提到应用程序中存在哪些线程,它们是如何创建的,它们如何交互等等,我现在假设只有一个线程。

如果UI线程是唯一的线程,问题显而易见:您的UI线程正在忙于运行正在进行的任务,并且没有花时间来呈现更新的UI。如果这是问题,这可能会解决它:

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

BeginInvoke强制所有Dispatcher操作高于输入优先级,以便在当前线程继续之前完成。

答案 1 :(得分:0)

Dispatcher在队列中工作。所以它可能是UI线程阻塞。您可以通过Dispatcher在队列中添加更多工作,但它永远不会被执行,因为UI线程正在阻塞。

也许试试这个:

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

这将使您的工作在工作的前面已经在队列中。因此,UI线程将完成工作,然后再次阻止。