c++ - 安全中断 C++11 阻塞操作

标签 c++ multithreading c++11 boost condition-variable

我有一个 std::thread,它使用 Boost 的 asio 从串口读取数据:

std::atomic<bool> quit(false);

void serialThread()
{
    try
    {
        asio::io_service io;
        asio::serial_port port(io);

        port.open("COM9"); // Yeay no port enumeration support!

        port.set_option(asio::serial_port_base::baud_rate(9600));

        while (!quit)
        {
            asio::streambuf buf;
            asio::read_until(port, buf, "\n");

            auto it = asio::buffers_begin(buf.data());
            string line(it, it + buf.size());

            doStuffWithLine(line);
        }
    }
    catch (std::exception e)
    {
        cout << "Serial thread error: " << e.what() << endl;
    }
}

void SetupSignals()
{
    // Arrange it so that `quit = true;` happens when Ctrl-C is pressed.
}

int main(int argc, char *argv[])
{
    SetupSignals();

    thread st(serialThread);

    st.join();

    return 0;
}

当我按下 Ctrl-C 时,我想干净地退出线程,以便适本地调用所有析构函数(如果您不这样做,Windows 上的某些驱动程序会讨厌它适本地关闭他们的资源)。

不幸的是,如您所见,当前代码块在 read_until() 中,因此当您按下 Ctrl-C 时,在收到新的文本行之前什么都不会发生。

一种解决方案是使用轮询,如下所示:

asio::async_read_until(port, buf, "\n", ...);
while (!quit)
    io.poll();

但我宁愿不使用轮询。这很不雅观。我目前能看到的唯一解决方案是有一个 std::condition_variable quitOrIoFinished,它在 quit 设置为 true 或读取完成时触发。但是我没有写 asio,所以我不能给它一个条件变量来等待。

是否有任何干净、理智的解决方案?在 Go 中,我只使用 select 来等待多个 channel ,其中一个是退出 channel 。不过,我在 C++ 中看不到类似的解决方案。

最佳答案

使用 asio::signal_set 等待 INT 信号(control-C 倾向于发送中断)。

当它到达时,只需对具有未决异步操作的 IO 对象调用 cancel()。它们将返回 error_code 等于 boost::asio::error::operation_aborted

现在,如果你有一个 io_service::work 对象,销毁它,所有运行 io_service::run() 的线程都会返回,这样你就可以加入它们.

注意 注意同步访问您的 IO 对象(例如,当您对它们调用 cancel() 时)因为这些对象不是线程安全的,与 io_servicestrand

关于c++ - 安全中断 C++11 阻塞操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35266314/

相关文章:

C# 锯齿状数组错误(元素并不总是设置)

java - 使用 Java 的高效 "Pinging"

c++ - 搜索一组独特的指针

c++ - 在不同的Visual Studio版本中缺少.dll

c++ - 嵌套类中的 "Invalid covariant return type"错误,其方法返回基于模板的对象

c++ - 未定义的引用链接 yaml-cpp 程序与 mingw-w64 + cmake

c# - 在 C# 中使用 BackgroundWorker 的线程问题

c++ - 基于范围的多维数组自动循环作为函数参数

C++ 并发写入 bool 数组(不是 std::vector)

c++ - 从赋值运算符函数调用复制构造函数