boost::asio串口异步接收数据失败,同步接收正常问题求助
问题分析与解决
核心问题:未启动io_context事件循环
Boost.Asio的所有异步操作都依赖io_context调度执行回调函数。你的代码仅发起了异步读操作,但从未启动io_context的事件循环,导致异步回调永远不会触发。
修复方案
必须调用io_context的run()、run_one()或poll()方法处理事件,以下是两种常用实现:
1. 主线程启动事件循环(推荐)
修改main.cpp:
SerialPort sp; int main() { sp.open_port("COM11"); sp.write_sync("Testing123"); sp.read_async(); // 启动io_context事件循环,阻塞到所有异步操作完成或被停止 sp.get_io_context().run(); return 0; }
同时在SerialPort.hpp中添加获取io_context的公开接口:
public: boost::asio::io_context& get_io_context() { return io; }
2. 独立线程运行事件循环
若不想阻塞主线程,可创建专门线程运行io_context:
在SerialPort.hpp中添加线程成员:
private: std::thread io_thread;
修改open_port方法启动线程:
bool SerialPort::open_port(void) { try { this->port.open(this->port_name); // 启动io_context线程 io_thread = std::thread([this](){ io.run(); }); return true; } catch (const std::exception& ex) { PLOG_FATAL << ex.what(); } return false; }
在析构函数中停止并等待线程:
SerialPort::~SerialPort() { io.stop(); if (io_thread.joinable()) io_thread.join(); }
其他潜在问题修复
- 持续接收需求:当前
read_handler仅处理一次数据,若要持续接收,需在回调末尾再次发起异步读:
void SerialPort::read_handler(const boost::system::error_code& error, std::size_t bytes_transferred) { if (!error) { std::string received_data_buffer; std::transform(this->read_buffer.begin(), this->read_buffer.begin() + bytes_transferred, std::back_inserter(received_data_buffer), [](std::byte character) { return static_cast<char>(character); }); PLOG_INFO << "In Read Buffer : " << received_data_buffer; // 再次发起异步读,保持持续接收 this->port.async_read_some(boost::asio::buffer(this->read_buffer.data(), this->read_buffer.size()), boost::bind(&SerialPort::read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { PLOG_ERROR << "Read error: " << error.message(); } }
- 串口参数校验:确保异步操作前已正确配置波特率、奇偶校验等串口参数(同步能工作不代表参数完全适配异步场景),示例:
port.set_option(boost::asio::serial_port_base::baud_rate(9600)); port.set_option(boost::asio::serial_port_base::character_size(8)); port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
内容的提问来源于stack exchange,提问作者Dark Sorrow
相关产品推荐
相关产品推荐

