【发布时间】:2017-01-30 03:35:58
【问题描述】:
我的目标:线程将等待(忙循环而不是睡眠),直到按下特定键(比如说 0)。每个线程都有一个不同的键,它将触发该线程退出等待并继续执行等待之后的命令。
我尝试了以下方法来实现这一点:
使用 conio.h 和 getch() 但这是旧的,不再适用于 gcc。来源:Why can't I find <conio.h> on Linux?
使用 ncurses.h 和 getch() 但这会在等待键盘按下时停止执行。 我使用的代码:http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/scanw.html#GETCHCLASS
我目前使用 termios.h 的实现:
int 主要:
//Keypress Event Handler
struct termios info;
tcgetattr(0, &info); /* get current terminal attirbutes; 0 is the file descriptor for stdin */
info.c_lflag &= ~ICANON; /* disable canonical mode */
info.c_cc[VMIN] = 1; /* wait until at least one keystroke available */
info.c_cc[VTIME] = 0; /* no timeout */
tcsetattr(0, TCSANOW, &info); /* set immediately */
线程调用的内部函数(抱歉缩进):
while(stop_wait != 1)
{
//printf("%d\n", temp->currentID);
ch = getchar();
if(ch < 0) {
if (ferror(stdin)) {
clearerr(stdin);
}
}
switch (ch)
{
case 48 :
if(temp->event == 0) stop_wait = 1;
break;
case 49 :
if(temp->event == 1) stop_wait = 1;
break;
case 50 :
if(temp->event == 2) stop_wait = 1;
break;
case 51 :
if(temp->event == 3) stop_wait = 1;
break;
case 52 :
if(temp->event == 4) stop_wait = 1;
break;
}
}
主要结束:
tcgetattr(0, &info);
info.c_lflag |= ICANON;
tcsetattr(0, TCSANOW, &info);
上面的代码与这里的代码非常相似:Implementing a KeyPress Event in C
但是,这并不能按照我想要的正确方式工作。我有一个输入文件,指定哪些键将触发 stop_wait 更改为 1。线程 1 将通过按键盘上的 1 触发(在 ascii 中为 49),线程 2 将通过按键盘上的 2 触发(在 ascii 中为 50 )。当前实现的问题是,如果不触发 1,则 2 不会触发。如下所示(Main() 语句显示执行结束忽略它所说的内容):
我可以就这个问题获得任何建议/帮助吗?
【问题讨论】:
-
' free running' 线程可以轮询状态以检测按键被按下并查看哪个按键并做出相应响应?
-
很多方案来决定如何对其进行微调。例如,没有键被丢弃。甚至每个线程都可能有一个fifo,并且“kbd inpt/dispatch”线程可以将消息排队到它需要发出信号的适当线程。在该方案中(无论您如何实现先进先出),您都可以确保您永远不会错过任何击键。例如,如果线程 1 需要为每次按下“a”做某事,它就永远不会错过按键
-
我没有那样看。谢谢!我会尝试实现它并看看,但我认为这肯定会奏效。
-
这可能不是您的情况所需要的,但我确实创建了一个工作示例(答案如下)。您可以调整轮询间隔(使用小于 1 部分的等待,而不是
sleep(),使用usleep())。你可能会弄乱排队策略。但值得测试 IMO 代码。 -
感谢您的关注。我刚刚更新了答案。我忘了 free() 分配的内存,所以我刚刚添加了那行。否则会泄漏内存。
标签: c multithreading ncurses termios conio