[英]Does non-blocking read from std::cin work with std::this_thread::sleep_for() or std::this_thread::yield() (IPC)
我在實現過程中遇到了一個特定的問題,無法找到解決方案。
我有一個兩部分的應用程序。 一部分是Java swing GUI。 第二部分是C ++應用程序,它執行所有(耗時的)計算邏輯。 這兩個進程(在兩個方向上)與其輸出和輸入流進行通信。 我現在的問題是,在C ++程序的一部分中,我必須等待來自Java程序的用戶輸入。 但是,等待似乎受阻。
當我在外殼中調用程序時,最合適的方法是:
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閱讀。 如果什么都沒有,我讓步,然后再試一次。
我知道,yield並不是一種很干凈的工作方式,但是我想使這兩個應用程序之間的通信盡可能簡單。 如果可能的話,沒有第三方庫,沒有更復雜的概念(如Sockets)。
但是,這種方法行不通,只是從std :: cin中讀取,其行為與第一種方法相同。 Java程序變得沒有響應,並且兩個應用程序似乎都不做任何事情。
如果在外殼中調用C ++應用程序,並且如果我從鍵盤提供相同的輸入,則C ++應用程序將完美運行,因此問題不應該存在。 如果我從C ++應用程序中刪除所有這些給定的代碼段,則Java應用程序會響應並正常工作-盡管顯然它沒有得到所需的輸入。
嘗試了很長時間以實現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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.