Условие цикла с использованием getch () не завершает цикл должным образом - PullRequest
0 голосов
/ 09 февраля 2019

У меня следующий код, но он не завершает цикл while, даже если done имеет значение true.Он продолжает ждать _getch():

   while (done || ((c = _getch()) != EOF))
   {
       cout << "Operation aborted" << endl;
       break;
   }
   cout << "Operation finished" << endl;

Редактировать: На самом деле я хочу иметь возможность прервать длинную операцию, выполняемую в другом потоке.Я считаю, что я должен присоединиться к теме после while цикла.Но с помощью следующего кода цикл не выполняется, когда я нажимаю клавишу.

thread t(Start, folder_path);
while (done || ((c = _getch()) != EOF))
{
    cout << "Operation aborted" << endl;
    exit_signal.set_value();
    break;
}
t1.join();
cout << "Operation finished" << endl;

Как я могу завершить цикл, когда done истинно?

1 Ответ

0 голосов
/ 09 февраля 2019

Условия цикла записываются следующим образом:

  • , если done истинно, логическое выражение замыкается накоротко, и тело цикла вводится без оценкиправая сторона условия.
  • если done ложно, то вызывается _getch().Если возвращается символ, выражение будет истинным, и тело цикла будет введено .Если нет доступных символов, _getch() будет ждать, пока пользователь не введет его.Только если конец файла встречается (т. Е. Ctrl + Z вводится в режиме терминала, или cin перенаправляется из файла и достигается его конец), цикл будет прерван.

Если вы хотите неблокирующую запись на клавиатуре, сначала вам нужно будет использовать _kbhit(), чтобы проверить, доступен ли символ, а затем только прочитать символс _getch().Для kbhit() в Linux вы можете посмотреть здесь .

Edit: ваш многопоточный редактор

Прежде всего, если done - это переменная, которая используется в обоих потоках (что, по-видимому, так и есть, поскольку она не изменена в цикле), убедитесь, что она объявила atomic.Если это не так, то у вас будет условие гонки: UB.

Теперь ваш рассказ не соответствует коду.Если done - это когда другой поток завершил работу, и вы хотите завершить цикл в данный момент, вам нужно включить цикл на !done.

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

Так чтокод будет иметь такую ​​структуру, как

std::atomic<bool> done(false); 
...
thread t(Start, folder_path);
while (!done)
{   
    if (_kbhit() && ((c = _getch()) != EOF) { // if keystroke available
        cout << "Operation aborted" << endl;
        exit_signal.set_value();  // assuming this would make t1 return from folder_path()
        break;
    }
    std::this_thread::sleep_for (std::chrono::milliseconds(500));
    // update status bar or do other stuff 
}
t1.join();
cout << "Operation finished" << endl;

Наконец, я не знаю, что делает exit_signal.set_value();.Я надеюсь, что он делает что-то, что говорит другому потоку прекратить обработку.Если этого не произойдет, ваш цикл завершится, но на join() вам все равно придется ждать завершения другого потока.

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