如何正确暂停/延迟 Windows 窗体应用程序

Posted

技术标签:

【中文标题】如何正确暂停/延迟 Windows 窗体应用程序【英文标题】:How to correctly pause/delay Windows Forms application 【发布时间】:2016-03-18 09:03:50 【问题描述】:

我是 OOP 和 C# 的初学者。

我正在使用 Windows 窗体开发一个问答游戏。 我的问题与两个类有关,formgame logic。 我有一个带有经典 Froms 控件的基本 UI。看看吧。

我想要实现的是,当玩家按下任何答案按钮时,它会用红色或绿色突出显示按下的按钮,具体取决于答案是正确还是错误。更改颜色后,我希望程序等待一段时间,然后转到下一个问题。

问题是,我不知道如何正确实现这一点。我不知道如何使用线程以及 Form 应用程序如何与线程相关。我应该使用线程睡眠、定时器还是异步?

我会告诉你游戏逻辑类中应该处理这个的方法。

public static void Play(char answer) //Method gets a char representing a palyer answer
    
        if (_rightAnswer == answer) //If the answer is true, the button should become green
        
            Program.MainWindow.ChangeBtnColor(answer, System.Drawing.Color.LightGreen);
            _score++;
        
        else //Otherwise the button becomes Red
        
            Program.MainWindow.ChangeBtnColor(answer, System.Drawing.Color.Red);
        

        //SLEEP HERE

        if (!(_currentIndex < _maxIndex)) //If it is the last question, show game over
        
            Program.MainWindow.DisplayGameOver(_score);
        
        else //If it is not the last question, load next question and dispaly it and finally change the button color to default
        
            _currentIndex++;
            _currentQuestion = Database.ListOfQuestions.ElementAt(_currentIndex);
            _rightAnswer = _currentQuestion.RightAnswer;
            Program.MainWindow.DisplayStats(_score, _currentIndex + 1, _maxIndex + 1);
            Program.MainWindow.DisplayQuestion(_currentQuestion.Text);
            Program.MainWindow.DisplayChoices(_currentQuestion.Choices);
        
        Program.MainWindow.ChangeBtnColor(answer, System.Drawing.SystemColors.ControlLight);
    

我不想完全阻止 UI,但我也不希望用户在暂停期间通过按其他按钮来进行其他事件。因为这会导致应用程序运行不正常。

【问题讨论】:

【参考方案1】:

如果程序非常简单并且您不想实现线程,我建议使用 Timer。单击回答按钮时只需启动您的计时器。您的计时器应包含在一段时间后自行停止并执行其他所需操作的功能(例如选择另一个问题)。

【讨论】:

【参考方案2】:

一旦用户选择了答案,您就可以禁用所有按钮,这样他们就不能按其他任何东西了。

然后启动一个计时器,这样您就不会阻塞 UI。计时器 基本上是一个线程,但会为您处理所有线程,因此您不必担心这方面的问题。

当计时器达到所需的延迟时,停止它并触发一个事件以选择下一个问题。

【讨论】:

【参考方案3】:

在 //SLEEP HERE 添加这行代码

Timer timer = new Timer(new TimerCallback(timerCb), null, 2000, 0);

2000是毫秒,是等待时间,timerCb是回调方法。

此外,禁用所有按钮,以便不会生成新事件。

private void timerCb(object state)
    
        Dispatcher.Invoke(() =>
        
            label1.Content = "Foo!";              
        );
    

你可以在回调中做任何你想做的事情,但是如果你做的事情会改变 UI 中的任何东西,你需要像我改变标签内容一样使用 Dispatcher。

【讨论】:

【参考方案4】:

感谢await,在 GUI 场景中暂停执行非常容易:

await Task.Delay(2000);

这不会阻塞用户界面。

您应该研究await 的作用以及如何使用它。如果您从未听说过它并且正在编写 WinForms,那么您做错了。

不需要计时器或线程。没有回调,没有Invoke

【讨论】:

以上是关于如何正确暂停/延迟 Windows 窗体应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 窗体应用程序设置中记录窗口位置

使用属性“暂停”线程

如何在 Windows 窗体中创建 GDI 泄漏!

窗体在 Windows 8 上显示错误的尺寸 - 如何获得真实尺寸?

JAVA中 如何使用延迟?

Lync Ucwa 绕过 Lync 客户端