使用boost::asio::use_future后boost::beast::http::async_write未执行
问题原因与解决方案
问题根源
原代码使用yield[ec]时,是在Boost.Asio协程上下文(由boost::asio::spawn创建)中运行,协程机制会自动驱动对应的io_context处理异步操作的调度与完成回调。而改用boost::asio::use_future后,你没有驱动io_context运行——Boost.Asio的所有异步操作都依赖io_context的事件循环来执行,没有运行io_context的话,async_write的写入逻辑根本不会被触发,导致future一直处于等待状态,最终超时。
解决办法
你需要确保io_context在异步操作期间处于运行状态,具体可以分两种场景处理:
场景1:单线程环境
如果你的代码在单线程中执行,在获取future后,直接调用io_context::run()即可,但要注意超时处理时需要停止io_context避免阻塞:
try{ auto& ioc = d_tcpStream->get_executor().context(); auto write_fut = boost::beast::http::async_write(*d_tcpStream, req, boost::asio::use_future); // 启动io_context事件循环,放在后台线程避免阻塞wait_for std::thread ioc_thread([&ioc]() { ioc.run(); }); if (write_fut.wait_for(std::chrono::seconds(10)) == std::future_status::timeout){ std::cout << "TIMEOUTTT" << std::endl; ioc.stop(); // 停止io_context,终止后台线程 ioc_thread.join(); return 1; }else{ auto bytes_tx = write_fut.get(); std::cout << "Number of Bytes transmitted: " << bytes_tx; ioc_thread.join(); } } catch (std::system_error& ex) { std::cerr << ex.what() << std::endl; }
场景2:已有io_context运行在其他线程
如果你的程序中已经有其他线程在调用io_context::run()(比如原协程场景中的io_context),那么只需确保该io_context没有被停止,异步操作会自动被调度执行,无需额外启动线程。此时可以简化代码:
try{ auto write_fut = boost::beast::http::async_write(*d_tcpStream, req, boost::asio::use_future); if (write_fut.wait_for(std::chrono::seconds(10)) == std::future_status::timeout){ std::cout << "TIMEOUTTT" << std::endl; return 1; }else{ auto bytes_tx = write_fut.get(); std::cout << "Number of Bytes transmitted: " << bytes_tx; } } catch (std::system_error& ex) { std::cerr << ex.what() << std::endl; }
额外注意事项
- 确保
req(HTTP请求对象)的生命周期覆盖整个异步操作过程,避免因对象提前销毁导致未定义行为。 - 如果多次调用
io_context::run(),注意在操作完成后调用io_context::reset(),以便后续重新启动事件循环。
内容的提问来源于stack exchange,提问作者Saurabh Vaidya
相关产品推荐
相关产品推荐

