[英]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()函数,并带有error operation_aborted错误。 当它切换回FREERUN时,也会发生相同的情况-在FREERUN情况下,当它到达server.run(error)时,它将调用CSerialBoost :: OnReadBlock()。
这很容易引起误解,因为它总是为其他模式调用该函数。 当我停止/取消IO服务时,我希望每种情况都调用其自己的函数(或不执行任何操作)。 我是否期望过高,或者这是正常操作? 难道我做错了什么? 请提示我该如何处理。 (我在Win XP和Win 7,Visual Studio 2010下使用boost:asio 1-5-3,我是新手来增强)
谢谢你,MA。
这是预期的行为。
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()
,将执行已取消操作的准备运行处理程序。
考虑以下任一情况:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.