如何使用 asio 执行非阻塞读取?
我正在尝试使用 boost::asio 从串行端口上的设备读取和写入。 当没有任何内容可读取时,boost::asio:read() 和 boost::asio::serial_port::read_some() 都会阻塞。 相反,我想检测这种情况并向端口写入命令以启动设备。
我怎样才能检测到没有可用数据?
如果有必要,我可以异步完成所有事情,如果可以的话,我宁愿避免额外的复杂性。
I am attempting to use boost::asio to read and write from a device on a serial port. Both boost::asio:read() and boost::asio::serial_port::read_some() block when there is nothing to read. Instead I would like to detect this condition and write a command to the port to kick-start the device.
How can I either detect that no data is available?
If necessary I can do everything asynchronously, I would just rather avoid the extra complexity if I can.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上,你有几个选择。 您可以使用串行端口的内置
async_read_some
函数,也可以使用独立函数boost::asio::async_read
(或async_read_some< /代码>)。
您仍然会遇到实际上被“阻止”的情况,因为除非(1)数据已被读取或(2)发生错误,否则这些都不会调用回调。 为了解决这个问题,您需要使用
deadline_timer
对象来设置超时。 如果首先触发超时,则没有可用数据。 否则,您将读取数据。增加的复杂性并不是那么糟糕。 您最终会得到两个具有相似行为的回调。 如果“读取”或“超时”回调因错误而触发,您就知道这是比赛的失败者。 如果其中任何一个调用没有错误,那么您就知道它是比赛获胜者(并且您应该取消另一个调用)。 在您原本要阻塞调用
read_some
的地方,您现在将调用io_svc.run()
。 当您的函数调用run
时,它仍然会像以前一样阻塞,但这次您可以控制持续时间。这是一个示例:
您只需在这里或那里进行一些调整即可开始满足您的特定需求。 我希望这有帮助!
另一个注意事项:不需要额外的线程来处理回调。 一切都在调用
run()
中处理。 不确定你是否已经意识到这一点......You have a couple of options, actually. You can either use the serial port's built-in
async_read_some
function, or you can use the stand-alone functionboost::asio::async_read
(orasync_read_some
).You'll still run into the situation where you are effectively "blocked", since neither of these will call the callback unless (1) data has been read or (2) an error occurs. To get around this, you'll want to use a
deadline_timer
object to set a timeout. If the timeout fires first, no data was available. Otherwise, you will have read data.The added complexity isn't really all that bad. You'll end up with two callbacks with similar behavior. If either the "read" or the "timeout" callback fires with an error, you know it's the race loser. If either one fires without an error, then you know it's the race winner (and you should cancel the other call). In the place where you would have had your blocking call to
read_some
, you will now have a call toio_svc.run()
. Your function will still block as before when it callsrun
, but this time you control the duration.Here's an example:
That should get you started with only a few tweaks here and there to suit your specific needs. I hope this helps!
Another note: No extra threads were necessary to handle callbacks. Everything is handled within the call to
run()
. Not sure if you were already aware of this...它实际上比这里暗示的答案要简单得多,并且您可以同步执行:
假设您的阻塞读取是这样的:
然后将其替换为
您使用 receive_from 的替代重载形式,几乎所有发送/接收方法都具有。 不幸的是,他们采用了 flags 参数,但 0 似乎工作正常。
Its actually a lot simpler than the answers here have implied, and you can do it synchronously:
Suppose your blocking read was something like this:
Then you replace it with
You use the alternative overloaded form of receive_from which almost all the send/receive methods have. They unfortunately take a flags argument but 0 seems to work fine.
您必须使用自由函数 asio::async_read。
You have to use the free-function asio::async_read.