Как правильно приостановить/задержать приложение Windows Forms

Я новичок в ООП и C#.

Я работаю над викториной, используя Windows Forms. Моя проблема связана с двумя классами: форма и логика игры. У меня есть базовый пользовательский интерфейс с классическими элементами управления Froms. Взглянем.

Макет пользовательского интерфейса

Я хочу добиться того, чтобы когда игрок нажимал любую кнопку ответа, он выделял эту нажатую кнопку красным или зеленым цветом, в зависимости от того, правильный это ответ или неправильный. После изменения цвета я хочу, чтобы программа немного подождала, а затем перешла к следующему вопросу.

Проблема в том, что я не знаю, как это сделать правильно. Я не знаю, как работать с потоками и как именно работает приложение 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);
    }

Я не хочу полностью блокировать пользовательский интерфейс, но также я не хочу, чтобы пользователи совершали другие действия, нажимая другие кнопки во время паузы. Потому что это приведет к неправильному запуску приложения.


person Community    schedule 12.12.2015    source источник


Ответы (4)


Если программа действительно проста и вы не хотите реализовывать потоки, я бы предложил использовать Timer. Просто запустите таймер при нажатии кнопки ответа. Ваш таймер должен содержать функцию, которая через некоторое время остановится и выполнит другие необходимые действия (например, выберет другой вопрос).

person Marcin Zdunek    schedule 12.12.2015

После того, как пользователь выбрал ответ, вы можете отключить все кнопки, чтобы он больше ничего не нажимал.

Затем запустите таймер, чтобы не блокировать пользовательский интерфейс. Таймер является в основном потоком, но обрабатывает все потоки за вас, поэтому вам не нужно беспокоиться об этом аспекте.

Когда таймер достигнет желаемой задержки, остановите его и запустите событие, чтобы выбрать следующий вопрос.

person ChrisF    schedule 12.12.2015

В //SLEEP HERE добавьте эту строку кода

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

2000 — это миллисекунды и время ожидания, timerCb — это метод обратного вызова.

Также при этом отключите все ваши кнопки, чтобы новые события не генерировались.

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

Вы можете делать все, что хотите, в обратном вызове, однако, если вы делаете что-то, что может изменить что-либо в пользовательском интерфейсе, вам нужно использовать Dispatcher, как я изменил содержимое метки.

person Steve    schedule 12.12.2015

Приостановить выполнение в сценарии с графическим интерфейсом очень просто благодаря await:

await Task.Delay(2000);

Это не блокирует пользовательский интерфейс.

Вы должны изучить, что делает await и как его использовать. Если вы никогда не слышали об этом и программируете WinForms, вы делаете что-то не так.

Не нужны ни таймеры, ни потоки. Никаких обратных вызовов, никаких Invoke.

person usr    schedule 12.12.2015