了解WPF Dispatcher.BeginInvoke [英] Understanding the WPF Dispatcher.BeginInvoke

查看:222
本文介绍了了解WPF Dispatcher.BeginInvoke的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的印象是,调度将跟随操作的优先级
排队,并执行基于优先级
的操作或在这种操作被添加到队列(如果优先级相同)
的顺序,直到有人告诉我,这是在的情况下,没有的情况下WPF UI调度



有人告诉我,如果UI线程上运行时间较长的持续时间说数据库中读取
的UI调度简单尝试执行下一组操作队列。
我不知道如何面对它,以便决定编写,其中包含一个按钮和三个矩形,按钮的点击样本WPF应用程序中,矩形填充不同的颜色。



<预类=郎HTML prettyprint-覆盖> <&StackPanel的GT;
<按钮X:NAME =FillColorsWIDTH =100HEIGHT =100
含量=填充颜色点击=OnFillColorsClick/>
< TextBlock的WIDTH =100文本={绑定顺序}/>
<矩形X:NAME =RectangleOne保证金=5WIDTH =100HEIGHT =100填充={结合BrushOne}/>
<矩形X:NAME =RectangleTwo保证金=5WIDTH =100HEIGHT =100填充={结合BrushTwo}/>
<矩形X:NAME =RectangleThree保证金=5WIDTH =100HEIGHT =100填充={结合BrushThree}/>
< / StackPanel的>

和代码隐藏

 私人无效OnFillColorsClick(对象发件人,RoutedEventArgs E)
{
无功调度= Application.Current.MainWindow.Dispatcher;

dispatcher.BeginInvoke(新动作(()=>
{
//dispatcher.BeginInvoke(new行动(SetBrushOneColor),(的DispatcherPriority)4);
//dispatcher.BeginInvoke(new动作(SetBrushTwoColor),(的DispatcherPriority)5);
//dispatcher.BeginInvoke(new行动(SetBrushThreeColor),(的DispatcherPriority)6);

调度.BeginInvoke(新动作(SetBrushOneColor));
dispatcher.BeginInvoke(新动作(SetBrushTwoColor));
dispatcher.BeginInvoke(新动作(SetBrushThreeColor));

}) ,(的DispatcherPriority)10);
}

私人无效SetBrushOneColor()
{
的Thread.Sleep(10 * 1000);
阶=一;
//MessageBox.Show(\"One);
BrushOne = Brushes.Red;
}

私人无效SetBrushTwoColor()
{
的Thread.Sleep(12 * 1000);
阶=二;
//MessageBox.Show(\"Two);
BrushTwo = Brushes.Green;
}

私人无效SetBrushThreeColor()
{
的Thread.Sleep(15 * 1000);
阶=三;
//MessageBox.Show(\"Three);
BrushThree = Brushes.Blue;
}

公共字符串订单
{
{返回_order; }

{
_order + =的String.Format({0},值);
RaisePropertyChanged(订单);
}
}



注释代码按预期工作的方法是基于调用在的DispatcherPriority ,我也能看到屏幕刷新每个操作完成后。
订单一,二,三。颜色绘制了一个又一个。



现在所在的的DispatcherPriority 未提及
的工作代码(我相信它会默认为正常)的顺序仍是一,二,三,但如果我表现出的MessageBox 方法里面,结果第三人利益弹出窗口显示第一则两个然后一个但是当我调试我能看到的方法是在搜索预期的顺序调用(甚至智能跟踪显示,显示一个消息框,但我不吨看到它在那个时候在屏幕上看到它最后一次操作完成之后。)它只是在的MessageBox ES显示在相反的顺序。



是因为 MessageBox.Show 是一个阻塞调用,操作的消息已经被关闭后会被清除。
即使是这样的的MessageBox的顺序也应该是二和 Three`?


解决方案

下来到你的代码的行为之前,它是理解的优先事项的先决条件调度的DispatcherPriority 分为范围,如下面的图片





如果你只是排队的调度 4的行动4上述范围。在前景队列将先被执行,那么背景,然后在最后待机队列。 。优先级0将不被执行



现在,您的代码:



三任务正在排队1日在背景,第二个在背景和3日在前景队列。所以第三个将得到优先执行。那么第二个任务,导致它具有更高的优先级,然后第一个任务。我希望将其清除。



虽然有些多观察将帮助您喜欢更好地理解,如果你已经设置了优先级,7,8和9。因此,作为本是前台排队,7将得到先执行然后7,然后8逐个并专门的顺序,虽然是越来越执行7,8和9等待,这意味着前景队列将得到同步执行到每个另一个。



背景待机队列不会以这种方式的情况下,执行是异步的其他任务,任务将按照优先级的表现。和第一个背景待机队列。



希望这个解释澄清在一定程度上。


I was under the impression that the dispatcher will follow the priority of the operations queued it and execute the operations based on the priority or the order in which the operation was added to the queue(if same priority) until I was told that this is no the case in case of the WPF UI dispatcher.

I was told that if a operation on the UI thread takes longer duration say a database read the UI dispatcher simple tries to execute next set of operations in the queue. I could not come to terms with it so decided to write a sample WPF application which contains a button and three rectangles, on click of the button, the rectangles are filled with different colors.

<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>

and in the 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");
    }
}

The commented code works as expected the methods are invoked based on the DispatcherPriority and I also get to see the screen refresh after each operation has been completed. Order is One, Two, Three. Colors are drawn one after another.

Now the working code where the DispatcherPriority is not mentioned ( I assume it would default to Normal) the order is still One, Two, Three but if I show a MessageBox inside the methods, the
Thrid popup is show first then Two then One but when I debug I could see the methods are
invoked in the expected order (IntelliTrace even shows that a message box is shown but I don't see it on the screen at that time and see it only after the last operation is finished.) its just that the MessageBoxes are shown in the reverse order.

Is it because MessageBox.Show is a blocking call and the operation are cleared after the message has been closed.
Even then the order of the MessageBox should also be One, Two andThree` ?

解决方案

Before coming down to your code behavior it's a prerequisite to understand the priorities of Dispatcher. DispatcherPriority is divided into ranges as shown in below image.

If you simply queue 4 actions to 4 above ranges on Dispatcher. the Foreground queue will get executed first, then the Background and then in last Idle queue. priority 0 will not get executed.

Now your code:

Three task are queued 1st in background, 2nd in background and 3rd in foreground queue. So 3rd will get executed first. then 2nd task cause it has higher priority then 1st task. I hope that clears it.

Although some more observation will help you understand it better like, what if you have set the priorities as 7,8 and 9. So as this is a foreground queue, 7 will get executed first then 7 and then 8. One by one and exclusively in that order and while 7 is getting executed, 8 and 9 will wait, meaning foreground queue will get executed synchronously to each another.

But Background and Idle queue will not behave in that way the where execution is asynchronous to other tasks and tasks will follow the priority. And first Background and the Idle queue.

Hope this explanation clarifies to some extent.

这篇关于了解WPF Dispatcher.BeginInvoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆