Linux 中的多线程程序中的 C++ 处理按键
C++ handle keypress in a multithread program in Linux
我正在编写一个同时从 4 个摄像头捕获视频的程序,所以我有 4 个线程来控制每个摄像头。在每个线程中,我希望它继续捕获,直到我按下一个键并且该键对应于 'q' 或其他内容。
对于按键句柄,我在网上搜索了一下,找到了这样的方法:
#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 中 class 我有这样的代码(不完整):
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 次,程序就会退出,控制权将交还给 shell。但在某些特定情况下(我不完全知道,它不会每次都发生)它会导致问题,那就是当我然后去输入命令到 shell 时,我输入的字符不不要出现。当我按下回车键时,命令被提交。
我搜索这个问题,发现这个:https://askubuntu.com/a/172747,这说明我的终端属性没有正确重置。但是在按键处理代码中我注意到这两行代码
tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr);
fcntl(STDIN_FILENO, F_SETFL, old_file_status);
确实重置了终端属性。所以我想知道它是否与多线程有关。我是多线程编程的新手,自己无法解决,有人可以帮助我吗?非常感谢任何建议。
您有多个线程试图同时更改(静态)终端的参数:
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);
如果不锁定,你的终端属性是完全随机的。
修复是用互斥锁保护它,或者如果你生成另一个线程来读取键盘并为 'q' 被按下时设置一个标志;您的其他线程可以读取的内容,您可以执行类似
的操作
(pardon the psudo code)
bool shouldRun = true
void captureThreadMain {
while (shouldRun) {
captureFrame();
}
}
void keyboardPressMain {
while (getKey('q'));
shouldRun = false;
}
这意味着您只需按一次 'q' 即可停止所有帧收集线程。
我正在编写一个同时从 4 个摄像头捕获视频的程序,所以我有 4 个线程来控制每个摄像头。在每个线程中,我希望它继续捕获,直到我按下一个键并且该键对应于 'q' 或其他内容。
对于按键句柄,我在网上搜索了一下,找到了这样的方法:
#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 中 class 我有这样的代码(不完整):
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 次,程序就会退出,控制权将交还给 shell。但在某些特定情况下(我不完全知道,它不会每次都发生)它会导致问题,那就是当我然后去输入命令到 shell 时,我输入的字符不不要出现。当我按下回车键时,命令被提交。
我搜索这个问题,发现这个:https://askubuntu.com/a/172747,这说明我的终端属性没有正确重置。但是在按键处理代码中我注意到这两行代码
tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr);
fcntl(STDIN_FILENO, F_SETFL, old_file_status);
确实重置了终端属性。所以我想知道它是否与多线程有关。我是多线程编程的新手,自己无法解决,有人可以帮助我吗?非常感谢任何建议。
您有多个线程试图同时更改(静态)终端的参数:
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);
如果不锁定,你的终端属性是完全随机的。 修复是用互斥锁保护它,或者如果你生成另一个线程来读取键盘并为 'q' 被按下时设置一个标志;您的其他线程可以读取的内容,您可以执行类似
的操作(pardon the psudo code)
bool shouldRun = true
void captureThreadMain {
while (shouldRun) {
captureFrame();
}
}
void keyboardPressMain {
while (getKey('q'));
shouldRun = false;
}
这意味着您只需按一次 'q' 即可停止所有帧收集线程。