【问题标题】:How to stop, from another thread, std::cin from reading anymore input?如何从另一个线程停止 std::cin 读取更多输入?
【发布时间】:2017-02-22 15:32:14
【问题描述】:

我启动了两个线程,thread t1 正在等待通过cin 输入。我可以将EOF 之类的东西从thread t2 放入cin 以阻止cin 阅读吗?我试过'\n'ios::eofbit。两者都不起作用。

#include <thread>
#include <iostream>
#include <string>
#include <condition_variable>

std::condition_variable cv;

void Foo()
{
    std::string sFoo;
    std::cin >> sFoo;
    // Do stuff with sFoo
}

void Bar()
{
    // Do stuff
    // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin.

    std::cin.setstate(std::ios::setstate(std::ios::eofbit); // Does not work
    std::cin.putback('\n'); // Does not work

    // maybe something similar like these above
}

int main()
{
    std::thread t1(Foo);
    std::thread t2(Bar);
}

【问题讨论】:

  • @KerrekSB 没有 cin.close() 函数...如果我错了请纠正我
  • 你是对的,没关系:-S
  • @Mario 试试::close( STDIN_FILENO );::fclose( stdin ); 甚至::close( 0 );。见stackoverflow.com/questions/288062/…有点过激了……
  • 您可以构建逻辑,如果 thread1 读取特定内容,则它可以退出。现在 thread2 可以 putback 特定的东西以便 thread1 退出。看这个例子(cplusplus.com/reference/istream/istream/putback)
  • @sameerkn 那么还是存在用户必须按回车键才能关闭cin读取的问题。

标签: c++ multithreading c++11 cin


【解决方案1】:

我不认为从 istream 进行标准的非阻塞读取或中断等待输入的线程的方法。您可能会尝试查看 boost asio 或 boost iostreams - 也许它们具有此功能。

您可以在 POSIX 系统上使用 select/poll 或在其他系统上使用它们的对应项来检查是否有任何数据可用,或者使用某种形式的中断读取 - API 也依赖于系统。

下面是一个有效的肮脏解决方案 - 您最终会得到一个泄漏的线程,该线程将永远在标准输入上等待,但它可以满足您的需求。

#include <thread>
#include <iostream>
#include <string>
#include <condition_variable>
#include <chrono>
#include <mutex>
#include <queue>

std::mutex m;
bool dataEnd = false;
std::queue<std::string> data;
std::condition_variable sAvail;

void Reader() {
    while (std::cin) {
        auto s = std::string();
        std::cin >> s;

        auto lock = std::unique_lock<std::mutex>(m);
        data.push(std::move(s));
        sAvail.notify_all();
    }
}

void Foo() {
    for (;;) {
        auto lock = std::unique_lock<std::mutex>(m);
        if (data.empty()) {
            sAvail.wait(lock);
            if (dataEnd) {
                std::cerr << "No more data!\n";
                break;
            }
        }

        if (!data.empty()) {
            auto s = std::move(data.front());
            data.pop();
            std::cerr << "Got " << s << '\n';
        }
    }
}

void Bar(std::thread& reader) {
    // Do stuff
    // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin.

    {
        auto lock = std::unique_lock<std::mutex>(m);
        dataEnd = true;
        sAvail.notify_all();
        reader.detach();
    }

    // maybe something similar like these above
}

int main() {
    std::thread r(Reader);
    std::thread t1(Foo);
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    std::thread t2(Bar, std::ref(r));

    t1.join();
    t2.join();
}

【讨论】:

    猜你喜欢
    • 2013-07-31
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多