Можно ли остановить cin от ожидания ввода? - PullRequest
9 голосов
/ 20 декабря 2011

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

Пока это работает хорошо, однако я не нашел хорошего решения, чтобы остановить выполнение этого потока.Поток всегда ожидает ввода пользователя:

 while(appRunning)
 {
     std::cin>>theUserCommand;
     // ...do stuff
 }

Затем, когда графическое приложение завершится, оно остановит все консольные функции, в которые я включил поток:

 appRunning = false;
 // do some more related clean up
 myListeningThread->join();

Каквы можете видеть, что std :: cin будет ожидать ввода пользователя после вызова соединения.Одно из решений, которое я попробовал, - это создание событий "синтезирующих нажатий клавиш", std :: cin получит любое значение, которое вы отправите с помощью ENTER, поток будет красиво завершен, это ужасное решение, и я не хочу его оставлять.Кроме того, он работал в одной из сред, в которых запускается инструмент, но не работает, когда я пытался использовать его вместе с API пользовательского интерфейса.Не могли бы вы, ребята, помочь мне, как я могу исправить это правильно?Неужели не могу точно сказать, есть ли в документации по C ++ функция остановки std :: cin, ожидающего ввода данных пользователем, и просто продолжения выполнения программы, возможно ли это?

EDIT: Fine Iобнаружим, что keybd_event немного вводит в заблуждение в некоторых средах, явно указав обработчик ввода с WriteConsoleInput.

1 Ответ

1 голос
/ 21 декабря 2011

Я не большой программист Windows, я знаю намного больше о Unix.И я совершенно незнаком с boost::thread.Тем не менее, основываясь на совете внизу этой страницы MSDN , вот моя рекомендация:

  • Создайте объект события перед созданием консоли-читание потока.
  • Если вы хотите завершить работу, вызовите SetEvent объекта события непосредственно перед вызовом ->join метода потока.
  • Измените основной цикл в потоке чтения консоли, чтобы блокировать WaitForMultipleObjects вместо istream::operator>>, примерно так:

    for (;;) {
        HANDLE h[2];
        h[0] = GetStdHandle(STD_INPUT_HANDLE);
        h[1] = that_event_object_I_mentioned;
        DWORD which = WaitForMultipleObjects(2, h, FALSE, INFINITE);
    
        if (which == WAIT_OBJECT_0)
            processConsoleCommand();
        else if (which == WAIT_OBJECT_0 + 1)
            break;
        else
            abort();
    }
    
  • Этот поток долженпозаботьтесь о том, чтобы не выполнять никаких операций блокировки, кроме вызова WaitForMultipleObjects.Согласно обсуждению в комментариях ниже, это означает, что processConsoleCommand не может использовать cin вообще.Вместо этого вам нужно будет использовать низкоуровневые консольные функции ввода , в частности GetNumberOfConsoleInputEvents и ReadConsoleInput, чтобы гарантировать, что вы не блокируете;вам нужно будет набирать символы во многих вызовах на processConsoleCommand, пока вы не прочитаете возврат каретки;и вам также нужно будет сделать свое собственное эхо.

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