可以阻止cin等待输入?

时间:2011-12-19 23:36:22

标签: c++ windows iostream blocking boost-thread

在图形应用程序中,我使用控制台输入执行调试命令。创建控制台时,还会创建一个新线程来收集处理所有输入的用户命令,图形应用程序继续并行运行。我使用boost :: thread库。

到目前为止它运行良好,但是我没有找到一个很好的解决方案来停止执行这个线程。线程总是在等待用户输入:

 while(appRunning)
 {
     std::cin>>theUserCommand;
     // ...do stuff
 }

然后当图形应用程序结束时,它将停止所有控制台功能,其中包括线程:

 appRunning = false;
 // do some more related clean up
 myListeningThread->join();

正如您所看到的,在调用连接之后,std :: cin将等待用户输入。 我尝试的解决方案之一是创建事件“合成击键”,std :: cin将获得你用ENTER发送的任何值,线程将很好地结束,这个解决方案是可怕的,我不想保留它。 此外,它确实在工具执行的其中一个环境中工作,但在我尝试将其与UI API一起使用时失败了。你能指导我怎样才能以正确的方式解决这个问题?无法确切地说,如果在C ++文档中有一个函数来阻止std :: cin等待用户输入,并且只是继续执行程序,它是否可能?

编辑:很好我发现keybd_event对某些环境有点误导,明确指定WriteConsoleInput的输入处理程序效果很好。

1 个答案:

答案 0 :(得分:1)

我不是一个Windows程序员,我对Unix知之甚多。而且我对boost::thread完全不熟悉。也就是说,根据this MSDN page底部的建议,这是我的建议:

  • 在创建控制台阅读线程之前创建event object
  • 如果要关闭,请在调用线程的->join方法之前立即调用事件对象上的SetEvent
  • 将控制台读取线程中的主循环更改为阻止WaitForMultipleObjects而不是istream::operator>>,如下所示:

    for (;;) {
        HANDLE h[2];
        h[0] = GetStdHandle(STD_INPUT_HANDLE);
        h[1] = that_event_object_I_mentioned;
        DWORD which = WaitForMultipleObjects(2, h, FALSE, INFINITE);
    
        if (which == WAIT_OBJECT_0)
            processConsoleCommand();
        else if (which == WAIT_OBJECT_0 + 1)
            break;
        else
            abort();
    }
    
  • 除了WaitForMultipleObjects调用之外,此线程必须注意不要执行任何阻止操作。根据以下评论中的讨论,这意味着processConsoleCommand根本无法使用cin。您需要使用low-level console input functions,尤其是GetNumberOfConsoleInputEventsReadConsoleInput,以确保您不会阻止;你需要在多次调用processConsoleCommand之前累积字符,直到你读回车票;你还需要做自己的回音。