Я пишу программу, которая захватывает видео с 4 камер одновременно, поэтому у меня есть 4 потока для управления каждой камерой. В каждом потоке я хочу, чтобы он продолжал захватывать, пока я не нажал клавишу, и этот ключ соответствует «q» или что-то еще.C++ handle keypress в многопоточной программе в Linux
Для нажатия клавиши ручки Я поиск в Интернете и найти способ, как это:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
int kbhit(int key) {
int ch;
int old_file_status;
struct termios old_term_attr;
struct termios new_term_attr;
tcgetattr(STDIN_FILENO, &old_term_attr);
new_term_attr = old_term_attr;
new_term_attr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &new_term_attr);
old_file_status = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, old_file_status | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr);
fcntl(STDIN_FILENO, F_SETFL, old_file_status);
if(ch == c)
return 1;
return 0;
}
И в моем классе VideoCapture у меня есть такой код (не полный):
static void *capureVideo(void *para) {
// Some code...
while(!(kbhit('q') {
// Read frame...
}
}
void creatThread() {
if (pthread_create(&threadID, NULL, capureVideo, this) != 0) {
perror("thread create faild");
exit(EXIT_FAILURE);
}
}
При запуске программы, , как только я нажимаю клавишу «q» 4 раза, программа заканчивается, и управление возвращается в оболочку. Но в некоторых определенных обстоятельствах (я точно не знаю, это не происходит каждый раз), это приводит к проблеме, то есть когда я затем перехожу и набираю команды в оболочку, символы, которые я печатаю, не отображаются. Когда я нажимаю, вводят команды.
Я ищу эту проблему и нашел следующее: https://askubuntu.com/a/172747, что указывает на то, что мои атрибуты терминала не были сброшены правильно. Но в коде рукописного ввода я заметил, что эти две строки кода
tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr);
fcntl(STDIN_FILENO, F_SETFL, old_file_status);
сбросил атрибуты терминала. Поэтому я задаюсь вопросом, относится ли это к многопоточному. Я новичок в программировании mutlithread и не могу решить его сам, так может кто-нибудь мне помочь? Любые предложения приветствуются.
Сброс атрибутов терминала вручную не будет абсолютно ничего, если программа будет прервана CTRL-C или каким-либо другим сигналом. Помимо явного сброса атрибутов терминала до их значений по умолчанию, обработчик сигнала должен быть настроен с помощью 'sigaction()' для, по крайней мере, 'SIGINT',' SIGHUP', 'SIGTERM' и, возможно,' SIGQUIT', которые сбросит атрибуты терминала до значений по умолчанию. –
Здесь также есть условие гонки, где один терминал сброса потока присваивает значение по умолчанию непосредственно перед тем, как другой поток входит в 'getchar()' и заканчивает блокировку стандартного ввода. Это, в общем, ошибочный подход. Терминал должен быть настроен на неблокирующий режим и неканонический режим обработки только один раз, в начале и сброс только до завершения программы. И вместо 'getchar()' use 'read()' в дескрипторе файла 0. –
'Терминал должен быть настроен на неблокирующий режим и неканонический режим обработки только один раз, в начале и сброс только до того, как программа завершится . Значит, я могу использовать одноэлементный шаблон? Кроме того, не могли бы вы объяснить, почему 'getchar()' не рекомендуется. Большое спасибо. @SamVarshavchik – Gzy