使用boost::asio::io_context实现多独立间隔方法调用的问题
C++定时任务常见问题解答
问题1:单线程io_context实现下的阻塞问题
单线程使用io_context时,所有任务都是串行执行的,必然会互相阻塞。比如你提到的场景:method_1每100秒调用一次,若method_1本身执行耗时(比如2秒),这2秒内io_context.run()会卡在method_1的执行逻辑上,无法处理method_2的定时触发事件,导致method_2的调用被延迟。
io_context.run()的工作逻辑是在当前线程中依次处理所有就绪的事件处理器(handler),它不会并行执行任务。只要某个方法的执行时间超过其他任务的间隔,就会导致其他任务的调用被阻塞。
问题2:多线程实现下方法未执行的常见原因
多线程方案中任务未执行,通常是以下几个核心原因:
- io_context提前退出:如果没有使用工作守护对象(
executor_work_guard),当io_context中没有待处理的任务时,run()会立即返回,线程直接结束。比如启动线程后,还没来得及提交定时任务,io_context.run()就已经退出。 - 定时器生命周期问题:如果定时器是局部变量(比如在函数栈上创建),函数执行完毕后定时器被销毁,对应的异步定时任务会被取消,自然不会执行。必须保证定时器的生命周期覆盖整个任务执行周期。
- 任务提交错误:比如定时器的
async_wait未正确绑定到目标方法,或者绑定过程中出现参数错误(比如未正确捕获this指针、函数签名不匹配)。 - 线程启动时机问题:如果在提交定时任务之前就调用了
io_context.run(),此时io_context没有任务,线程会直接退出,后续提交的任务不会被处理。
典型错误代码示例(导致任务不执行)
#include <asio.hpp> #include <thread> #include <iostream> void method_1() { std::cout << "method_1 called\n"; } int main() { asio::io_context io; // 错误:定时器是局部变量,main函数结束前就被销毁 asio::steady_timer t(io, asio::chrono::seconds(1)); t.async_wait([](const asio::error_code&){ method_1(); }); // 错误:没有work_guard,io_context.run()会立即返回 std::thread t1([&io](){ io.run(); }); t1.join(); return 0; }
修正后的多线程示例
#include <asio.hpp> #include <thread> #include <iostream> #include <memory> void method_1() { std::cout << "method_1 called\n"; } void method_2() { std::cout << "method_2 called\n"; } void method_3() { std::cout << "method_3 called\n"; } template<typename Func> void schedule_repeating(asio::io_context& io, int interval_sec, Func func) { auto timer = std::make_shared<asio::steady_timer>(io, asio::chrono::seconds(interval_sec)); timer->async_wait([&io, interval_sec, func, timer](const asio::error_code& ec) { if (!ec) { func(); schedule_repeating(io, interval_sec, func); } }); } int main() { asio::io_context io; // 工作守护对象,防止io_context.run()无任务时退出 auto work_guard = asio::make_work_guard(io); // 提交三个定时任务 schedule_repeating(io, 100, method_1); schedule_repeating(io, 1, method_2); schedule_repeating(io, 5, method_3); // 启动多线程处理io_context事件 std::thread t1([&io](){ io.run(); }); std::thread t2([&io](){ io.run(); }); t1.join(); t2.join(); return 0; }
内容的提问来源于stack exchange,提问作者Ashkanxy
相关产品推荐
相关产品推荐

