【发布时间】:2016-02-08 09:36:32
【问题描述】:
我有一个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();
但我宁愿不使用轮询。这很不雅。我目前能看到的唯一解决方案是在quit 设置为true 或读取完成时触发std::condition_variable quitOrIoFinished。但是我没有写 asio 所以我不能给它一个条件变量来等待。
有什么干净、理智的解决方案吗?在 Go 中,我只需使用 select 来等待多个频道,其中一个是退出频道。不过,我在 C++ 中看不到类似的解决方案。
【问题讨论】:
-
很确定有一种方法可以指定
asio::read_until的超时时间。将该超时设置为 200 毫秒,并在重试之前检查您是否应该退出。 -
是的,这只是不那么激进的轮询...我想要一个非轮询解决方案。
标签: c++ multithreading c++11 boost condition-variable