You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何同时运行两个boost::asio::io_context实例以解决树莓派双连接运行异常问题?

解决Boost.Asio多个io_context同时运行的问题

这个问题我之前也碰到过,Boost.Asio的io_context.run()本身是阻塞式的——它会一直处理队列里的异步任务,直到没有待执行的任务才会返回。所以你先调用io.run(),程序就会卡在这一行,永远到不了io_context.run()那一步。给你两个实用的解决方案,按需选择:

方案1:用线程分别运行每个io_context

给每个io_context单独开一个线程,让它们的run()在不同线程里并行执行,这样就不会互相阻塞了。修改你的main函数如下:

boost::asio::io_context io_context;
boost::asio::io_context io;

int main() {
    // 创建服务器对象以接受客户端的连接请求
    tcp_server server(io_context);
    open_port_arduino();
    start = std::chrono::high_resolution_clock::now(); // 初始化时间
    
    // 每隔2秒向Arduino写入数据
    tim.expires_after(boost::asio::chrono::seconds {2});
    tim.async_wait(timer_handler);
    // 从Arduino读取数据
    start_read_arduino();

    // 启动一个线程专门运行Arduino相关的io_context
    std::thread arduino_io_thread([&]() {
        io.run();
    });

    // 主线程运行TCP服务器的io_context
    io_context.run();

    // 等待Arduino线程结束,避免程序提前退出
    arduino_io_thread.join();
}

需要注意:如果其中一个io_context的所有任务都完成了(比如TCP服务器被关闭),对应的run()会返回,这时候你可以根据需求调用另一个io_context的stop()方法,让程序正常退出。

方案2:合并到同一个io_context(更推荐)

Boost.Asio官方其实更推荐尽量使用单个io_context来管理所有异步操作,除非你有明确的隔离需求(比如不同任务需要不同的线程优先级)。把TCP服务器、Arduino串口操作、定时器都绑定到同一个io_context,这样只需要调用一次run()就可以了,代码更简洁,还能避免线程管理的麻烦。

修改后的代码大概是这样:

// 只保留一个io_context
boost::asio::io_context io;

int main() {
    // TCP服务器也使用这个io_context
    tcp_server server(io);
    // 注意:open_port_arduino()、start_read_arduino()里的异步操作,
    // 也要改成使用这个io对象(比如串口对象的构造要传入io)
    open_port_arduino();
    start = std::chrono::high_resolution_clock::now();

    // 定时器同样绑定到这个io_context
    tim.expires_after(boost::asio::chrono::seconds {2});
    tim.async_wait(timer_handler);
    start_read_arduino();

    // 只需要运行一次,就能处理所有异步任务
    io.run();
}

这个方案是最省心的,因为所有异步任务都在同一个事件循环里处理,不需要额外管理线程,也减少了线程同步的潜在问题。

额外提示:用work_guard保持io_context存活

如果你的某个io_context可能出现“暂时没有任务”的情况(比如Arduino暂时没有数据可读,也没有定时器任务),run()会自动返回,导致对应的线程退出。这时候可以用work_guard来让io_context一直保持“忙碌”状态,直到你主动停止它:

boost::asio::io_context io;
// 创建work guard,让io_context不会因为没有任务而退出
auto work_guard = boost::asio::make_work_guard(io);

std::thread arduino_thread([&]() {
    io.run();
});

// 当你需要停止的时候,重置work guard或者调用stop()
// work_guard.reset();
// io.stop();

内容的提问来源于stack exchange,提问作者Bia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 04:14:05