Ho avuto l'impressione che il dispatcher
seguirà la priorità delle operazioni in coda e di eseguire le operazioni in base alla priorità o l'ordine in cui l'operazione è stata aggiunta alla coda (se stessa priorità) fino a quando non mi è stato detto che questo non è il caso nel caso dello WPF UI dispatcher
.Capire il WPF Dispatcher.BeginInvoke
Mi è stato detto che se un'operazione sul thread dell'interfaccia utente richiede una maggiore durata, dire che un database legge il dispatcher dell'interfaccia utente tenta semplicemente di eseguire il successivo gruppo di operazioni nella coda. Non ho potuto venire a patti con esso, quindi ho deciso di scrivere un'applicazione WPF di esempio che contiene un pulsante e tre rettangoli, al clic del pulsante, i rettangoli sono riempiti con colori diversi.
<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>
e nel code-behind
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");
}
}
Il codice commentato funziona come previsto i metodi vengono richiamati in base alla DispatcherPriority
e ho anche arrivare a vedere l'aggiornamento dello schermo dopo ogni operazione è stata completata. Order
è One, Two, Three
. I colori sono disegnati uno dopo l'altro.
Ora il codice di lavoro in cui l'DispatcherPriority
non è menzionato (presumo che sarebbe di default per Normal
) l'ordine è ancora One, Two, Three
ma se io mostro un MessageBox
all'interno dei metodi, il Thrid
comparsa è mostrare in primo luogo poi Two
poi One
ma quando eseguo il debug, vedo che i metodi sono
richiamati nell'ordine previsto (IntelliTrace mostra anche che viene visualizzata una finestra di messaggio ma non la vedo sullo schermo in quel momento e la vedo solo dopo che è stata completata l'ultima operazione.) è solo che gli MessageBox
sono mostrati nell'ordine inverso.
È perché MessageBox.Show
è una chiamata di blocco e l'operazione viene cancellata dopo che il messaggio è stato chiuso.
Anche in questo caso l'ordine di MessageBox
dovrebbe essere One
, Two and
Tre`?
Questo è semplicemente influenzato dall'ordine in cui si chiudono le finestre di messaggio. Poiché l'ultimo è in cima, questo è il primo che chiudi. Non ha nulla a che fare con DispatcherPriority. –
Sì .. Ho pensato così, ma non sono in grado di vedere l'altro 'MessageBox'es prima di chiudere quello più in alto. –
@ Vignesh.N la mia risposta spiega la tua domanda? –