【问题标题】:Get user input without blocking while loop using threads in C使用C中的线程在不阻塞while循环的情况下获取用户输入
【发布时间】:2019-04-11 20:10:36
【问题描述】:

我想在 while 循环内从用户那里获取一个值,即变量的设定值,而不会阻塞其他任务的执行。我正在尝试使用 pthreads,但我的试验失败了。即使我正在使用 pthread,程序也会被 scanf 函数阻止。

这就是我在 main() 函数中创建 pthread 的方式

uint16_t refAngle = 0;
char refAngleString[64];

int main(void)
{
   pthread_t thread_id;

   while(1) {
       pthread_create(&thread_id, NULL, threadUserInput, NULL);
       pthread_join(thread_id, NULL);

       // Other functions were called below ...
   }
}

然后我有线程函数命名 threadUserInput

void *threadUserInput(void* vargp)
{
    scanf("%s", refAngleString);
    refAngle = (uint16_t) atoi(refAngleString);
    printf("Angle is: %d\n", refAngle);

    return NULL;
}

任何帮助将不胜感激,在此先感谢。

【问题讨论】:

  • 此函数:threadUserInput() 缺少语句:(void)vargp;,语句:return NULL; 应为:pthread_exit( NULL );
  • 关于:scanf("%s", refAngleString); 这对允许用户输入的单词的长度没有限制,这可能导致输入缓冲区溢出,从而导致未定义的行为格式字符串需要一个 MAX CHARACTERS 修饰符,它比输入缓冲区的长度小 1,因为 '%s' 总是将 NUL 字节附加到输入。使用 MAX CHARACTERS 修饰符可以避免任何可能的缓冲区溢出并避免任何未定义行为的可能性
  • 关于:`while(1) { pthread_create(&thread_id, NULL, threadUserInput, NULL); pthread_join(thread_id, NULL); // 下面调用了其他函数 ... }` 这导致程序每次通过循环都停止。建议:pthread_create(&thread_id, NULL, threadUserInput, NULL); while(1) { // Other functions were called below ... } pthread_join(thread_id, NULL); 然后修改线程函数为循环而不是当前的单通
  • 您的最新推荐成功了,谢谢!
  • 建议使用pthread_mutex,这样在主函数处理该变量时,没有竞争条件会导致线程输入变量

标签: c linux pthreads user-input


【解决方案1】:

虽然我使用的是 pthread,但程序还是被 scanf 函数阻塞了。

嗯,是的。创建的线程阻塞在scanf(),父线程阻塞在pthread_join(),等待对方。我很难找到任何好的理由来启动单个线程然后立即加入它,而不是直接调用线程函数。

如果您想在循环的每个迭代中获取一次用户输入,但在不等待该输入的情况下执行一些其他处理(在同一迭代中),那么解决方案是将 pthread_join() 调用移至所有工作可以在收到用户输入之前完成:

   while (1) {
       pthread_create(&thread_id, NULL, threadUserInput, NULL);

       // do work that does not require the user input ...

       pthread_join(thread_id, NULL);

       // do work that _does_ require the user input (if any) ...
   }

或者,也许您正在寻找更加解耦的东西,循环在输入可用之前进行尽可能多的迭代。在这种情况下,您应该在循环外部启动 I/O 线程并保持它运行,在输入后读取输入。当有输入可供主线程使用时,让它提供某种信号。从示意图上看,可能如下所示:

   pthread_create(&thread_id, NULL, threadAllUserInput, NULL);

   while (1) {

       // ... some work ...

       if (get_input_if_available(/* arguments */)) {
           // handle user input ...
       }

       // ... more work ...
   }

   force_input_thread_to_stop();
   pthread_join(thread_id, NULL);

我省略了如何实现get_input_if_available()force_input_thread_to_stop() 的所有细节。有多种选择,其中一些比其他更适合您的特定需求。

【讨论】:

    猜你喜欢
    • 2014-12-09
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    相关资源
    最近更新 更多