boost::asio 调用了错误的串行端口处理程序
boost::asio calls the wrong handler for serial port
对于嵌入式系统接口,我正在实现一个具有多达 8 种读取模式的类(下面的代码仅说明了两种 - FREERUN 和 BLOCKRUN)用于读取串行端口。此读取器的简化 ReaderTest() 函数如下所示:
void CSerialBoost::ReaderTest()
{
while (RUNflag)
switch (RUNstate) {
case FREERUN:
port.async_read_some(asio::buffer(TextIn, SZTXT),
boost::bind(&CSerialBoost::OnReadFree, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
server.reset();
server.run(error); // it calls OnReadBlock() here
break;
case BLOCKRUN:
port.async_read_some(asio::buffer(TextIn, SZTXT),
boost::bind(&CSerialBoost::OnReadBlock, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
server.reset();
server.run(error); // it calls OnReadFree() here
break;
default: break;
}
port.cancel(error); // cancel all IO operations
}
类 CSerialBoost 具有以下成员:
asio::io_service server;
asio::serial_port port;
asio::error_code error;
volatile int RUNstate; // reader mode
volatile int RUNflag; // start/stop flag
当我从一种模式切换到另一种模式时出现意外行为。假设没有传入数据并且代码在 FREERUN 中运行,为了从另一个线程切换到 BLOCKRUN,我这样做:
RUNstate = BLOCKRUN;
server.stop(); // unblock the event loop
该操作切换到 BLOCKRUN,因为它应该,当它到达 BLOCKRUN 案例下的 server.run(error) 行时,它会调用 CSerialBoost::OnReadFree() 函数,错误operation_aborted。当它切换回 FREERUN 时也会发生同样的情况 - 当它在 FREERUN 案例下到达 server.run(error) 时,它会调用 CSerialBoost::OnReadBlock()。
这是非常具有误导性的,因为它总是调用其他模式的函数。当我停止/取消 IO 服务时,我希望每个案例都调用自己的函数(或不调用)。是我期望过高,还是这是正常操作?我做错了什么吗?请提示我如何处理这个问题。(我在 Win XP 和 Win 7、Visual Studio 2010 下使用 boost:asio 1-5-3,我是 boost 的新手)
谢谢你,马。
预期的行为。
io_service::stop()
和io_service::reset()
只控制io_service
的事件循环的状态;都不会影响计划用于延迟调用(准备运行)的处理程序或用户定义的处理程序对象的生命周期。
在调用server.run()
时,async_read_some
操作已排队进入io_service
。 当事件循环通过 server.stop()
显式停止时,如果尚未调用操作的完成处理程序,则操作或完成处理程序将保持排队io_service
。 然后,执行在while
循环中继续,port.cancel()
强制取消port
上的未完成操作,将其完成处理程序设置为准备运行,错误代码为 boost::asio::error::operation_aborted
。 因此,下次调用server.run()
时,将执行已取消操作的准备运行的处理程序。
请考虑以下任一情况:
- 运行
io_service
完成。 这通常需要设置状态、取消未完成的操作以及防止完成处理程序将其他工作发布到io_service
中。 Boost.Asio 提供了一个官方的超时示例,此处还显示了从io_service
运行到完成的超时方法。 - 让异步调用链实现状态机。 这将避免
stop()
、reset()
和重新run()
io_service
的需要。 - 控制
io_service
对象的生命周期,因为io_service
的析构函数将导致所有未完成的处理程序被销毁 在此答案中可以找到一种方法。
- Qt Q串行端口未编程设备未关闭
- 在 linux c++ 中没有通过串行端口发送的数据
- 检查串行端口Linux中是否有传入数据(cbInQue for linux)
- 在不传输的情况下更改 Win32 中的串行端口波特率
- 增强 ASIO 和串行端口异步读取
- 串行端口写入究竟如何从缓冲区实际写入数据?
- 如何将参数这些串行端口传递到函数中
- 从 C/C++ 访问 Android 中的串行端口
- Qt两个串行端口发送和接收
- 通过串行端口从GPS传感器读取
- 提升 asio 串行端口"end of file"
- 通过串行端口发送多个值
- 与QSerialPort配合使用的串行端口仿真
- 如何通过boost::asio和shared_ptr创建串行端口
- 串行端口编码
- 使用来自串行端口的字符串数据来操作振镜扫描仪在更高的速度下会出错
- 写入和读取十六进制 TRAM QT 串行端口
- Qt串行端口数据接收
- Qt modbus 串行端口流量控制处理
- boost::asio 调用了错误的串行端口处理程序