线程睡眠和绘画用户界面

本文关键字:绘画 用户界面 线程 | 更新日期: 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