我寫了一個程序,它可以同時從4個攝像頭捕獲視頻,所以我有4個線程來控制每個攝像頭。在每個線程中,我希望它繼續捕獲,直到我點擊一個鍵,並且該鍵對應於'q'或某物。C++在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次程序退出並且控制回到shell。但在某些特定情況下(我不完全知道,它不會每次都發生)導致出現問題,也就是說,當我隨後將命令輸入到shell中時,我輸入的字符未顯示出來。當我按下輸入命令提交。
我搜索這個問題,發現這個:https://askubuntu.com/a/172747,這表明我的終端屬性沒有正確重置。但在按鍵處理代碼中我注意到這兩行代碼
tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr);
fcntl(STDIN_FILENO, F_SETFL, old_file_status);
確實重置了終端屬性。所以我想知道它是否與多線程相關。我是多線程編程的新手,無法自己解決,所以有人可以幫助我嗎?任何建議,高度讚賞。
如果程序以CTRL-C或其他信號終止,手動重置終端屬性將完全沒有任何作用。除了明確地將終端屬性重置爲默認值以外,還應該通過sigaction()至少爲SIGINT,SIGHUP,SIGTERM和SIGQUIT建立一個信號處理程序,會將終端屬性重置爲其默認值。 –
這裏還有一個競爭條件,其中一個線程重置終端在不同線程進入'getchar()'之前屬性爲默認值,並最終在標準輸入上阻塞。總的來說,這是一種錯誤的方法。終端應該只在開始時設置爲非阻塞模式和非規範處理模式一次,並且僅在程序終止之前復位。而不是'getchar()'在文件描述符0處使用'read()'。 –
'終端應該設置爲非阻塞模式和非規範處理模式,一開始只有一次,並且只在程序終止之前復位這是否意味着我可以使用單例模式?另外,你能否解釋爲什麼'getchar()'不被推薦。非常感謝你。 @SamVarshavchik – Gzy