C++ 在 Linux 中的多线程程序中处理按键

标签 c++ linux multithreading keypress

我正在编写一个同时从 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 类中,我有这样的代码(不完整):

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);
    }    
}

当程序运行时,一旦我按了 4 次“q”键,程序就会退出,控制权将交还给 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”即可停止所有帧收集线程。

关于C++ 在 Linux 中的多线程程序中处理按键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40359678/

相关文章:

java - 为什么 Thread.interrupt() 会这样?

c++ - 第二线程永远不会触发

c++ - 使用系统 DBus 的 registerService 失败(但适用于 session DBus)

c++ - XSLT 到 HTML 的转换。 Qt5中的generate-id()错误

linux - 有什么方法可以显示包含 'find' 、 'xargs' 的命令生成的命令?

linux - 在SUSE-Linux服务器上下载Internet Explorer

c# - 从线程增加 Int 时的竞争条件

C++类成员变量知道自己的偏移量

c++ - 正在获取 C++11 中 std::vector::operator[](size) 未定义行为的地址

c++ - 果酱 UI 生成器