我很困惑为什么我不能在 Count() 方法中的 Dispatcher 上使用“BeginInvoke”来使此测试计数器应用程序与 2 个(或更多)同时运行的 countertextbox 一起使用。
您可以通过将 BeginInvoke 替换为 Invoke 来解决该问题。但这并不能解决我的困惑。
这是我正在讨论的示例代码:
public class CounterTextBox : TextBox
{
private int _number;
public void Start()
{
(new Action(Count)).BeginInvoke(null, null);
}
private void Count()
{
while (true)
{
if (_number++ > 10000) _number = 0;
this.Dispatcher.BeginInvoke(new Action(UpdateText), System.Windows.Threading.DispatcherPriority.Background, null);
}
}
private void UpdateText()
{
this.Text = "" + _number;
}
}
当你使用Dispatcher.BeginInvoke
这意味着它时间表给定的操作稍后在 UI 线程中执行,然后返回控制权以允许当前线程继续执行。Invoke
阻止调用者,直到计划的操作完成。
当你使用BeginInvoke
你的循环将会运行super快自BeginInvoke
立即返回。这意味着您要添加lot and lots消息队列的操作。你正在添加它们much比它们实际处理的速度要快。这意味着从您安排消息到它实际有机会运行之间有很长的时间。
您正在运行的实际操作使用该字段_number
. But _number
正在被另一个线程修改很快 and 当操作在队列中时。这意味着它不会显示的值_number
在你安排动作的时候,而是在它在非常紧密的循环中继续进行之后。
如果你使用Dispatcher.Invoke
相反,它可以防止循环“超出自身”并具有多个计划事件,从而确保它写入的值始终是“当前”值。此外,通过强制循环的每次迭代都等待消息运行,这使得循环变得不那么“紧”,因此它通常无法运行得那么快。
如果你想使用BeginInvoke
你真正需要做的第一件事就是放慢循环速度。如果你希望它每秒更新一次文本,或者每 10 毫秒更新一次,或者其他什么,那么你可以使用Thread.Sleep
等待适当的时间。
接下来,您需要复印一份_number
在将其传递给之前Dispatcher
以便它显示您计划时的值,而不是执行时的值:
while (true)
{
if (_number++ > 10000)
_number = 0;
int copy = _number;
this.Dispatcher.BeginInvoke(new Action(() => UpdateText(copy))
, System.Windows.Threading.DispatcherPriority.Background, null);
Thread.Sleep(200);
}
private void UpdateText(int number)
{
this.Text = number.ToString();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)