线程睡眠和绘画用户界面
本文关键字:绘画 用户界面 线程 | 更新日期: 2023-09-27 18:32:00
我有一个红绿灯程序,可以模拟我住的地方附近的一个奇怪的十字路口。我很确定我有逻辑。我有函数来表示灯光的所有可能状态,包括黄色。问题是我的黄灯都没有画画。在汽车停到一个灯前五秒钟后,没有其他汽车通过绿灯,适当灯的黄灯应该亮起三秒钟,然后变成绿色。出于某种原因,当我逐步完成我的程序时,没有黄灯正在绘画。这是我的代码:
private void WaitThreeSecs()
{
//somehow I think this is to blame
int threeSeconds = 3000;
Thread.Sleep(threeSeconds);
}
private void FromStateOneToTwo()
{
//Stop Countdown Timers
fiveSec.Stop();
thirtySec.Stop();
//Indicate Current State
CurrentState = 2;
//Paint lights
BottomGreen.Fill = gray;
BottomYellow.Fill = yellow; // this never happens
BottomRed.Fill = gray;
//Wait 3 secs
WaitThreeSecs();
btnbottom.Content = "Car Stops";
//Call function that changes the state for other lights to be green
StateTwo();
}
FromStateOneToTwo() 在五秒后被调用,但指示灯永远不会是黄色的。我不知道为什么这不会发生。从按下按钮到适当的灯从红色直接变为绿色,灯等待 8 秒,这意味着我的 3 秒计时器正在工作,但我绘制的灯没有。 (我像在这里一样在其他功能中绘画,它工作正常)
如果需要,我可以显示更多/所有代码。
您不会得到跨线程InvalidOperation
异常,因此我假设提供的函数在 UI 线程上运行。如果您通过单击按钮或DispatcherTimer
的已用事件调用它,则会发生这种情况。
通过休眠 UI 线程,您不会给它时间来绘制屏幕。它切换颜色,然后返回,无需运行绘画方法。
最好的解决方案是使用标准Timer
这样你就不在 UI 线程上,然后使用 Dispatcher.BeginInvoke
(WPF) 或 Control.Invoke
(WinForms) 封送对 UI 线程所做的更改。您还可以消除Thread.Sleep
并制作更多计时器来触发下一个更改。
在WaitThreeSecs()
强制刷新屏幕之前使用 Application.DoEvents