У меня создалось впечатление, что dispatcher будет следовать приоритету
операций, поставленных в очередь, и выполнения операций на основе приоритета
или порядок, в котором операция была добавлена в очередь (если такой же приоритет)
пока мне не сказали, что это не так в случае WPF UI dispatcher.
Мне сказали, что если операция в потоке пользовательского интерфейса занимает больше времени, скажем, что чтение базы данных диспетчер 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, но если я покажу a MessageBox внутри методов, всплывающее окно Thrid появится сначала, затем Two, затем One, но когда я отлаживаю, я мог видеть, что методы запускаются в ожидаемом порядке (IntelliTrace даже показывает, что отображается окно сообщения, но я не вижу его на экране в то время и вижу его только после завершения последней операции.) его просто, что MessageBox es показаны в обратном порядке.
Это потому, что MessageBox.Show является блокирующим вызовом, и операция очищается после того, как сообщение было закрыто.
Даже тогда порядок MessageBox также должен быть One, Two and Three`
