我已对以下 DoRead 函数进行了编码,该函数从打开的串行端口读取数据,并且除以下事项外,它均按预期工作:
这是我的代码:
std::size_t wxSerialPort::DoRead(std::string& str, const int timeout)
{
m_bytes_transferred_read = 0;
boost::asio::async_read(m_serialPort, boost::asio::buffer(str),
std::bind(&wxSerialPort::AsyncReadHandler, this,
std::placeholders::_1, std::placeholders::_2));
m_io_context.restart();
if (timeout == wxTIMEOUT_INFINITE)
{
m_io_context.run_until(std::chrono::steady_clock::time_point::max());
}
else
{
m_io_context.run_for(std::chrono::milliseconds(timeout));
}
return m_bytes_transferred_read; // At this point I always get 0 bytes read.
}
void wxSerialPort::AsyncReadHandler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
m_bytes_transferred_read = bytes_transferred;
}
请记住,任何以 m _ 开头的变量都是成员变量。
但是,如果我为该函数提供了一个小的缓冲区,那么读取处理程序将在超时之前被调用,并且我会获得读取的实际字节数。
谢谢。
答案 0 :(得分:0)
听起来您需要致电async_read_some
而不是async_read
。
async_read函数确保:在异步操作完成之前已读取请求的数据量,即,在调用读取处理程序之前,它需要足够的数据来填充缓冲区。
无论何时缓冲区已满,basic_serial_port::async_read_some方法都会调用read处理程序。
因此,只需将对async_read
的调用替换为:
m_serialPort.async_read_some(boost::asio::buffer(str),
std::bind(&wxSerialPort::AsyncReadHandler, this,
std::placeholders::_1, std::placeholders::_2));
答案 1 :(得分:0)
事实证明,boost-asio-按设计 -,不会为任何 io_context :: run_for 调用任何IO处理程序当超时时间过去时,strong>, io_context :: run_one_for , io_context :: run_until 和 io_context :: run_one_until 起作用。
解决此问题的方法是提供我们自己的 wait handler 和 cancel ( basic_serial_port :: cancel )所有异步操作与该等待处理程序中的串行端口相关联,这将依次以 boost :: asio :: error :: operation_aborted 错误代码触发读取处理程序。
结果代码如下:
std::size_t wxSerialPort::DoRead(std::string& str, const int timeout)
{
m_bytes_transferred_read = 0;
if (timeout == wxTIMEOUT_INFINITE)
{
m_timer.expires_at(std::chrono::steady_clock::time_point::max());
}
else
{
m_timer.expires_from_now(std::chrono::milliseconds(timeout));
}
m_timer.async_wait(std::bind(&wxSerialPort::AsyncWaitHandler, this,
std::placeholders::_1));
boost::asio::async_read(m_serialPort, boost::asio::buffer(str),
std::bind(&wxSerialPort::AsyncReadHandler, this,
std::placeholders::_1, std::placeholders::_2));
m_io_context.restart();
m_io_context.run();
return m_bytes_transferred_read;
}
void wxSerialPort::AsyncReadHandler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (error != boost::asio::error::operation_aborted)
{
m_timer.cancel();
}
m_bytes_transferred_read = bytes_transferred;
}
void wxSerialPort::AsyncWaitHandler(const boost::system::error_code& error)
{
if (error != boost::asio::error::operation_aborted)
{
m_serialPort.cancel();
}
}
谢谢。