我的实现遇到了一个特定问题,无法找到解决方案。
我有一个由两部分组成的应用程序。一部分是Java swing GUI。第二部分是一个C ++应用程序,它执行所有(耗时的)计算逻辑。这两个进程(在两个方向上)与它们的输出和输入流进行通信。我现在的问题是,在C ++程序的一部分中,我必须等待来自Java程序的用户输入。然而,等待似乎阻止了。
当我在shell中调用程序时,完美的工作是:
std::string inputLine1;
std::cin >> inputLine1;
使用Java UI时,这当然不起作用,因为从std :: cin读取是阻塞的,因此当C ++应用程序等待输入时,Java应用程序无法执行任何操作。
因此我采用了另一种方式从std :: cin读取(至少在我的脑海中)应该工作,但我不能使它工作。它是:
std::string inputLine1;
while (true)
{
int c = std::cin.peek();
if (c != EOF)
{
std::cin >> inputLine1;
break;
}
std::this_thread::yield();
}
我还试图用
替换yield()行std::this_thread::sleep_for(std::chrono::milliseconds(500));
在我看来,这段代码应该如下:我看一下std :: cin。如果有什么东西,我从cin读到它。如果没有,我会屈服并稍后再试。
我知道,屈服被认为不是一种非常干净的工作方式,但我希望尽可能简化这两个应用程序之间的沟通。如果可能的话,没有第三方库,没有更复杂的概念(如套接字)。
然而,这种方法不起作用,它提供了与第一种方法相同的行为,只需从std :: cin读入。 Java程序没有响应,两个应用程序似乎都没有做任何事情。
如果在shell中调用C ++应用程序是完美的,如果我从键盘提供相同的输入,那么问题就不应该存在。如果我从C ++应用程序中删除所有这些给定的代码片段,Java应用程序就会响应并且有效 - 尽管它显然无法获得所需的输入。
答案 0 :(得分:0)
在尝试了很长时间来实现cin的非阻塞输入后,我很确定不可能让它始终如一地工作。
我目前的解决方案是将阻塞cin放入它自己的小线程中并让它做它的事情。
我为这个例子简化了我的实现,因为你需要某种线程安全的存储系统。
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
// Super simple thread safe storage
std::queue<std::string> Database;
std::mutex Padlock;
void PushLine(std::string Line) {
std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
Database.push(Line);
}
bool IsLineAvailable(void) {
std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
return !Database.empty();
}
std::string PopLine(void) {
std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
std::string Line(std::move(Database.front()));
Database.pop();
return Line;
}
// Main function with "non-blocking" input from cin
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
std::thread InputThread = std::thread([](){
do {
// Ensure the input is as clean as possible
if (std::cin.rdbuf()->in_avail()) {
std::cin.ignore(std::cin.rdbuf()->in_avail());
}
std::cin.clear();
// Get a line, cin will block here.
std::string Line;
std::getline(std::cin, Line);
// If the line is not empty attempt to store it.
if (!Line.empty()) {
PushLine(Line);
}
} while (1);
});
// Detach from the thread, it will never end.
InputThread.detach();
// A job to do.
unsigned int Counter = 0;
// Run your program.
bool Running = true;
while(Running) {
// Perform a job, in this case counting.
Counter++;
// Check for available input
if (IsLineAvailable()) {
// If there is input available, first get it
std::string Line = PopLine();
// Echo it to the terminal
std::cout << "Command: " << Line << std::endl;
// Perform actions based on the command
if (Line == "quit") {
Running = false;
}
else if (Line == "count") {
std::cout << " Count: " << Counter << std::endl;
}
}
// Sleep for a while
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Done.
return 0;
}