【问题标题】:Why is Dispatcher.Invoke not triggering UI update?为什么 Dispatcher.Invoke 不触发 UI 更新?
【发布时间】:2010-06-17 23:35:31
【问题描述】:

我正在尝试重用 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 代码的其余部分?

【问题讨论】:

  • 如何更新窗口中的进度条?它必须在单独的线程中完成,但是使用调度程序。

标签: c# wpf dispatcher


【解决方案1】:

您的最后一段提到线程两次,这增加了存在一个或多个后台线程的可能性。但是由于您没有提及应用程序中存在哪些线程,它们是如何创建的,它们如何交互等,所以我暂时假设只有一个线程。

如果 UI 线程是唯一的线程,那么问题就很明显了:您的 UI 线程正忙于运行正在进行的任务,并且没有花费时间来渲染更新的 UI。如果这是问题所在,这可能会解决它:

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

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

【讨论】:

    【解决方案2】:

    调度程序在队列上工作。所以可能是 UI 线程被阻塞了。您通过 Dispatcher 在队列中添加更多工作,但由于 UI 线程阻塞,它永远不会被执行。

    不妨试试这个:

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

    这会将您的工作置于已在队列中的工作之前。所以 UI 线程会完成工作,然后再次阻塞。

    【讨论】:

      猜你喜欢
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-02
      • 2012-10-18
      • 1970-01-01
      • 2011-03-08
      • 2021-10-17
      相关资源
      最近更新 更多