我试图使用boost :: asio从串口上的设备读取和写入.当没有任何东西要读时,boost :: asio:read()和boost :: asio :: serial_port :: read_some()都会阻塞.相反,我想检测这种情况并向端口写一个命令以启动设备.
如何检测到没有可用数据?
如果有必要,我可以异步地做所有事情,如果可以的话,我宁愿避免额外的复杂性.
实际上,你有几个选择.您可以使用串行端口的内置async_read_some
功能,也可以使用独立功能boost::asio::async_read
(或async_read_some
).
您仍将遇到有效"阻止"的情况,因为除非(1)数据已被读取或(2)发生错误,否则这些都不会调用回调.要解决这个问题,您需要使用一个deadline_timer
对象来设置超时.如果超时首先触发,则没有可用的数据.否则,您将读取数据.
增加的复杂性并不是那么糟糕.最终会有两个具有类似行为的回调.如果"读取"或"超时"回调触发错误,您就会知道它是失败者.如果其中任何一个没有发生错误,那么你知道它是比赛获胜者(你应该取消另一个电话).在您可以拨打电话的地方read_some
,您现在可以拨打电话io_svc.run()
.您的功能在呼叫时仍会像之前一样阻止run
,但这次您可以控制持续时间.
这是一个例子:
void foo() { io_service io_svc; serial_port ser_port(io_svc, "your string here"); deadline_timer timeout(io_svc); unsigned char my_buffer[1]; bool data_available = false; ser_port.async_read_some(boost::asio::buffer(my_buffer), boost::bind(&read_callback, boost::ref(data_available), boost::ref(timeout), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); timeout.expires_from_now(boost::posix_time::milliseconds(<>)); timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port), boost::asio::placeholders::error)); io_svc.run(); // will block until async callbacks are finished if (!data_available) { kick_start_the_device(); } } void read_callback(bool& data_available, deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred) { if (error || !bytes_transferred) { // No data was read! data_available = false; return; } timeout.cancel(); // will cause wait_callback to fire with an error data_available = true; } void wait_callback(serial_port& ser_port, const boost::system::error_code& error) { if (error) { // Data was read and this timeout was canceled return; } ser_port.cancel(); // will cause read_callback to fire with an error }
这应该让你开始只需要一些调整,以满足您的特定需求.我希望这有帮助!
另一个注意事项:不需要额外的线程来处理回调.一切都在通话中处理run()
.不确定你是否已经意识到这一点......