簡體   English   中英

從std :: cin進行的非阻塞讀取是否與std :: this_thread :: sleep_for()或std :: this_thread :: yield()(IPC)一起使用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM