Byłem pod wrażeniem, że dispatcher
pójdą priorytet operacji kolejce ją i wykonać operacje na podstawie priorytetu lub kolejności, w którym operacja została dodana do kolejki (jeśli ten sam priorytet) , dopóki nie powiedziano mi, że tak nie jest w przypadku WPF UI dispatcher
.Zrozumienie WPF Dispatcher.BeginInvoke
Powiedziano mi, że jeśli operacja na wątku UI trwa dłużej, powiedzmy, że baza danych odczytuje , program rozsyłający UI próbuje wykonać następny zestaw operacji w kolejce. Nie mogłem pogodzić się z nim, więc zdecydowałem się napisać przykładową aplikację WPF, która zawiera przycisk i trzy prostokąty, po kliknięciu przycisku prostokąty są wypełnione różnymi kolorami.
<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>
aw opóźnieniem kodu
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");
}
}
komentowanym kod działa zgodnie z oczekiwaniami metody są wywoływane na podstawie DispatcherPriority
i ja również dostać się do zobaczyć odświeżania ekranu po każdym operacja została zakończona. Order
jest One, Two, Three
. Kolory są rysowane jedna po drugiej.
Teraz kod działa gdzie DispatcherPriority
nie wspomniano (zakładam, że to domyślnie Normal
) kolejność jest nadal One, Two, Three
ale jeśli wykazują MessageBox
wewnątrz sposobach Thrid
popup jest pokazać pierwszy wtedy Two
następnie One
ale gdy debuguję, widzę, że metody są wywoływane w oczekiwanej kolejności (IntelliTrace pokazuje nawet, że okno komunikatu jest wyświetlane, ale nie widzę go na ekranie w tym czasie i widzę je dopiero po zakończeniu ostatniej operacji.) to tylko, że MessageBox
es są pokazane w odwrotnej kolejności.
Czy to dlatego, że MessageBox.Show
jest połączeniem blokującym, a operacja jest czyszczona po zamknięciu wiadomości.
Nawet wtedy zamówienie MessageBox
powinno być również One
, Two and
Trzy "?
Jest to po prostu zależne od kolejności zamykania skrzynek. Ponieważ ostatnia jest na wierzchu, jest to pierwsza, którą zamykasz. Nie ma nic wspólnego z DispatcherPriority. –
Tak .. Tak myślałem, ale nie jestem w stanie zobaczyć innych "MessageBox" zanim zamknę najwyższy. –
@ Vignesh.N czy moja odpowiedź wyjaśnia twoje zapytanie? –