Входной опрос в цикле while (true) в другом потоке работает только один раз

Я создал приложение для секундомера. В его конструкторе я запустил новый поток, в котором есть цикл while(true) для проверки нажатий на клавиатуру - при нажатии Space секундомер остановится; при попадании в A секундомер возобновляет работу. Это работает один раз для каждого, однако после этого он не регистрируется, и кажется, что цикл больше не работает или что-то в этом роде, потому что я помещаю журнал внутри цикла while (но вне операторов if), и он не печатается каждый цикл как я и предполагал. (Обратите внимание, что мне пришлось включить hasPressedSpace и hasPressedA booleans, потому что события ввода регистрировались несколько раз во время одного нажатия клавиши).

namespace StopWatch
{
    class Program
    {
        static void Main(string[] args)
        {
            StopWatch stopWatch = new StopWatch();
            stopWatch.Start();
        }
    }

    public class StopWatch
    {
        public TimeSpan Duration { get; private set; }
        private bool _hasStoppped;
        private ThreadStart threadStart;
        private Thread thread;
        private bool isPaused;

        public StopWatch()
        {

            Duration = new TimeSpan();
            threadStart = new ThreadStart(KeyBoardThread);
            thread = new Thread(threadStart);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        public void Start()
        {

            while (!_hasStoppped)
                {

                    Thread.Sleep(100);
                    Duration += TimeSpan.FromMilliseconds(100);
                    Console.WriteLine("Duration: " + Duration);

                }
        }


        void KeyBoardThread()
        {

            bool hasPressedSpace = false;
            bool hasPressedA = false;

            while (true)
            {


            if (Keyboard.IsKeyDown(Key.Space) && !hasPressedSpace)
                {

                    hasPressedSpace = true;
                    hasPressedA = false;
                    Stop();
                }

            if (Keyboard.IsKeyDown(Key.A) && !hasPressedA)
                {
                    hasPressedSpace = false;
                    hasPressedA = true;
                    _hasStoppped = false;
                    Start();
                }

            }


            }

         void Stop()
        {
            Console.WriteLine("stop called");
            _hasStoppped = true;

        }
    }
}

Есть ли конкретная причина, по которой вы использовали опрос, а не подход, управляемый событиями?

John Wu 12.03.2018 17:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
282
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавьте следующую строку в конец вашей основной функции:

Console.WriteLine("Exit");

Вы увидите, что после нажатия клавиши Space программа печатает «Выход». Тогда это, ну, выход!

Проблема здесь:

while (!_hasStoppped)
{
    Thread.Sleep(100);
    Duration += TimeSpan.FromMilliseconds(100);
    Console.WriteLine("Duration: " + Duration);
}

Если _hasStoppped - это true, поток завершается, и ваша программа тоже. Вам нужно переосмыслить свою логику.

Вы также можете отметить, что Stopwatch класс встроен в .NET Framework :)

Привет, спасибо, я добавил цикл while (true) вокруг исходного цикла while, и он работает. Однако до сих пор не понимаю, как это не работало раньше. Если основной поток завершается, когда _hasstoppped = true, то как он может перезапуститься при нажатии «A», а затем он больше не принимает никаких входных данных?

Adam J 13.03.2018 14:36

@AdamJ Рад услышать, что мой ответ помог. Вы можете принять ответ, щелкнув галочку / галочку слева от него, прямо под стрелками вверх / вниз. Чтобы ответить на следующий вопрос: когда вы нажимаете пробел, вы вызываете Stop(), который устанавливает _hasStoppped = true. Когда вы нажимаете A, вы устанавливаете _hasStoppped = false. Не уверен насчет второго пункта - я бы рекомендовал использовать .NET StopWatch и подписываться на ключевые события вместо вашего текущего подхода.

Stephen Kennedy 13.03.2018 14:41

Другие вопросы по теме