简体   繁体   English

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

[英]How to correctly pause/delay Windows Forms application

I am a beginner to the OOP and the C#. 我是OOP和C#的初学者。

I am working on a quiz game using the Windows Forms. 我正在使用Windows窗体进行问答游戏。 My problem is related to two classes, the form and the game logic . 我的问题与形式游戏逻辑这两个类有关。 I have a basic UI with classic Froms controls. 我有一个带有经典Froms控件的基本UI。 Take a look. 看一看。

用户界面布局

The thing I want to achieve is, when a player presses any answer button, it will higlight that pressed button by red or green color, depending on if it is right or wrong answer. 我要实现的目标是,当玩家按下任意一个答案按钮时,它将根据红色或绿色显示该按钮的亮点,具体取决于答案是对还是错。 After changing the color I want the program to wait for a while and then go to the next question. 更改颜色后,我希望程序等待一段时间,然后转到下一个问题。

Probelm is, that I don´t know how to achieve this correctly. Probelm是,我不知道如何正确实现这一目标。 I don´t know how to work with threads and how exactly the Form app works related to threads. 我不知道如何使用线程以及Form应用程序与线程相关的工作方式。 Should I use a thread sleep or a timer or a async? 我应该使用线程睡眠还是计时器或异步?

I will show you the method in game logic class which should handle this. 我将向您展示游戏逻辑类中应该处理的方法。

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);
    }

I don´t want to completely block the UI but also I don´t want users to make other events by pressing other buttons during the pause. 我不想完全阻止UI,但也不想让用户在暂停期间按其他按钮来进行其他事件。 Because it will result in improper run of app. 因为这会导致应用程序运行不正确。

If the program is really simple and you do not want to implement Threads I would suggest using Timer. 如果程序真的很简单,并且您不想实现线程,则建议使用Timer。 Just start your Timer when clicking answer button. 单击答案按钮时,只需启动计时器即可。 Your timer should contain function which would stop itself after some time and do other actions needed (eg pick another question). 您的计时器应包含一些功能,该功能会在一段时间后自行停止并执行其他需要执行的操作(例如,选择另一个问题)。

Once the user has selected an answer you can disable all the buttons so they can't press anything else. 用户选择答案后,您可以禁用所有按钮,以便他们无法按其他任何按钮。

Then start a timer so you don't block the UI. 然后启动计时器,这样就不会阻塞UI。 The timer is basically a thread but handles all the threading for you so you don't have to worry about that aspect. 计时器基本上一个线程,但处理所有的线程给你,让你不必担心这方面。

When the timer reaches the desired delay stop it and fire an event to select the next question. 当计时器达到所需的延迟时,停止计时器并触发一个事件以选择下一个问题。

At //SLEEP HERE add this line of code 在// SLEEP HERE处添加以下代码行

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

The 2000 is milliseconds and is the wait time, timerCb is a call back method. 2000是毫秒,是等待时间,timerCb是回调方法。

Also under that disable all your buttons so new events wont be generated. 还要在此禁用所有按钮,以便不会生成新事件。

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

You can do whatever you want in the callback, however if you do something that would change anything in the UI, you need to use the Dispatcher like I have changing the label content. 您可以在回调中做任何您想做的事,但是,如果您做的事情会改变UI中的任何内容,则需要使用Dispatcher,就像我更改了标签内容一样。

Suspending execution in a GUI scenario is very easy thanks to await : 由于await ,在GUI场景中暂停执行非常容易:

await Task.Delay(2000);

This does not block the UI. 这不会阻止UI。

You should research what await does and how to use it. 您应该研究await功能以及如何使用它。 If you have never heard about it and are programming WinForms you are doing something wrong. 如果您从未听说过它,并且正在对WinForms进行编程,则说明您做错了什么。

No timers or threads are needed. 不需要计时器或线程。 No callbacks, no Invoke . 没有回调,没有Invoke

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM