我正在尝试重用 UserControl 并借用一些跟踪进度的逻辑。我会尝试简化事情。 MyWindow.xaml 包含一个 MyUserControl。 MyUserControl 有自己的进度指示器(正在格式化...、正在复制文件...等),我想在 MyWindow 窗体的某处反射(reflect)此进度。但是,用户控件有一些我不太明白的逻辑。我读了又读,但我仍然不理解 Dispatcher。以下是用户控件中更新进度的逻辑摘要。
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 设置为以下方法,该方法设置用于窗口自身进度指示器的 View 模型属性。
private void SetActivation(bool activateInProgress)
{
viewModel.ActivationInProgress = activateInProgress;
}
但是,窗口的进度指示器永远不会改变。所以,我确信 Dispatcher.Invoke 正在做一些我不明白的事情。如果我在 SetActivation 方法中放置一个消息框,线程就会阻塞并且窗口的进度指示器会更新。我了解基本的线程,但是整个 Dispatcher 对我来说都是新的。我错过了什么?
更新:它现在似乎正在工作。事实证明,进度更新得太快了,以至于它从未显示在屏幕上。但是,我仍然想了解为什么 Dispatcher.Invoke 完成了(这是我没有编写的现有代码)。为什么操作内容不与 *.xaml.cs 代码的其余部分一致?
最佳答案
您的最后一段提到线程两次,这增加了存在一个或多个后台线程的可能性。但是由于您没有提到应用程序中存在哪些线程、它们是如何创建的、它们如何交互等,我暂时假设只有一个线程。
如果 UI 线程是唯一的线程,问题就很明显:您的 UI 线程正忙于运行正在进行的任务,而没有花时间呈现更新后的 UI。如果这是问题所在,这可能会解决它:
viewModel.ActivationInProgress = activateInProgress;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
new Action(() => {}));
BeginInvoke 强制所有高于输入优先级的 Dispatcher 操作在当前线程继续之前完成。
关于c# - 为什么 Dispatcher.Invoke 不触发 UI 更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3041798/