Jer*_*rev 28 c# multithreading invoke dispatcher begininvoke
我很困惑为什么我不能让这个测试计数器应用程序使用Count()方法在我的Dispatcher上使用"BeginInvoke"的2个(或更多个)同时运行的反文本框.
您可以通过Invoke替换BeginInvoke来解决问题.但这并不能解决我的困惑.
这是我正在谈论的示例代码:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Ser*_*rvy 75
使用Dispatcher.BeginInvoke它意味着它会在稍后的某个时间点调度给定的操作以在UI线程中执行,然后返回控制以允许当前线程继续执行. Invoke阻止调用者,直到计划的操作完成.
当你用BeginInvoke你的循环将运行超级因为快速BeginInvoke回报的时候了.这意味着你要添加很多和很多的行动,以消息队列.您添加它们的速度比实际处理速度快得多.这意味着从您安排消息到实际有机会运行之间需要很长时间.
您正在运行的实际操作使用该字段_number.但是_number正在被其他线程非常快速地修改并且该动作在队列中.这意味着它不会显示_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);
}
Run Code Online (Sandbox Code Playgroud)
private void UpdateText(int number)
{
this.Text = number.ToString();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40054 次 |
| 最近记录: |