У меня создалось впечатление, что 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`