我的印象是dispatcher
将遵循优先权
操作排队并根据优先级执行操作
或操作被添加到队列的顺序(如果相同的优先级)
直到我被告知WPF UI dispatcher
的情况并非如此。
有人告诉我,如果UI线程上的操作持续时间较长,则表示数据库已读取 UI调度程序简单地尝试执行队列中的下一组操作。 我无法接受它,所以决定编写一个示例WPF应用程序,其中包含一个按钮和三个矩形,点击按钮,矩形填充不同的颜色。
<StackPanel>
<Button x:Name="FillColors" Width="100" Height="100"
Content="Fill Colors" Click="OnFillColorsClick"/>
<TextBlock Width="100" Text="{Binding Order}"/>
<Rectangle x:Name="RectangleOne" Margin="5" Width="100" Height="100" Fill="{Binding BrushOne}" />
<Rectangle x:Name="RectangleTwo" Margin="5" Width="100" Height="100" Fill="{Binding BrushTwo}"/>
<Rectangle x:Name="RectangleThree" Margin="5" Width="100" Height="100" Fill="{Binding BrushThree}"/>
</StackPanel>
和代码隐藏
private void OnFillColorsClick(object sender, RoutedEventArgs e)
{
var dispatcher = Application.Current.MainWindow.Dispatcher;
dispatcher.BeginInvoke(new Action(() =>
{
//dispatcher.BeginInvoke(new Action(SetBrushOneColor), (DispatcherPriority)4);
//dispatcher.BeginInvoke(new Action(SetBrushTwoColor), (DispatcherPriority)5);
//dispatcher.BeginInvoke(new Action(SetBrushThreeColor), (DispatcherPriority)6);
dispatcher.BeginInvoke(new Action(SetBrushOneColor));
dispatcher.BeginInvoke(new Action(SetBrushTwoColor));
dispatcher.BeginInvoke(new Action(SetBrushThreeColor));
}), (DispatcherPriority)10);
}
private void SetBrushOneColor()
{
Thread.Sleep(10 * 1000);
Order = "One";
//MessageBox.Show("One");
BrushOne = Brushes.Red;
}
private void SetBrushTwoColor()
{
Thread.Sleep(12 * 1000);
Order = "Two";
//MessageBox.Show("Two");
BrushTwo = Brushes.Green;
}
private void SetBrushThreeColor()
{
Thread.Sleep(15 * 1000);
Order = "Three";
//MessageBox.Show("Three");
BrushThree = Brushes.Blue;
}
public string Order
{
get { return _order; }
set
{
_order += string.Format("{0}, ", value);
RaisePropertyChanged("Order");
}
}
注释代码按预期工作,基于DispatcherPriority
调用方法,并且每次操作完成后我也会看到屏幕刷新。
Order
是One, Two, Three
。颜色是一个接一个地绘制的。
现在没有提到DispatcherPriority
的工作代码
(我假设默认为Normal
)订单仍为One, Two, Three
,但如果我在方法中显示MessageBox
,则Thrid
弹出窗口首先显示然后Two
然后One
但是当我调试时我可以看到方法是按预期的顺序调用的(IntelliTrace甚至显示一个消息框显示但是我没有看到它当时的屏幕,只有在最后一次操作完成后才能看到它。)只是MessageBox
es以相反的顺序显示。
是否因为MessageBox.Show
是阻止呼叫,并且在消息关闭后清除了操作。
即使这样,MessageBox
的顺序也应该是One
,Two and
三个??
答案 0 :(得分:4)
在了解代码行为之前,先了解Dispatcher
的优先级。 DispatcherPriority
分为范围,如下图所示。
如果您只是将4个操作排到Dispatcher
上的4个以上范围。首先执行Foreground
队列,然后执行Background
,然后执行最后Idle
队列。优先级0不会被执行。
现在您的代码:
三个任务在background
排队第一,background
排名第二,foreground
排队第三排队。所以第3次将首先被执行。然后第二个任务导致它具有比第一个任务更高的优先级我希望能够清除它。
虽然更多观察将有助于您更好地理解它,如果您将优先级设置为7,8和9,那么如果这是一个前台队列,则先执行7然后执行7然后执行8。一个且完全按照该顺序执行,当7执行时,8和9将等待,这意味着foreground
队列将彼此同步执行。
但是Background
和Idle
队列不会以这种方式执行,其中执行与其他任务异步,任务将遵循优先级。首先是Background
和Idle
队列。
希望这种解释在某种程度上得到澄清。