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

类中实现两个异步定时器:延迟启动第二个时输出异常问题

Boost.Asio定时器生命周期异常输出问题解决

问题现象

想要实现第二个定时器在第一个启动0.5秒后运行,但当前代码执行后,第二个print对象仅输出Last num 0就终止,无法完成正常的计数逻辑;而不设置启动延迟时,两个定时器都能正常工作。

当前终端输出:

0,
1,
Last num 0,
2,
3,
4,
Last num 5.

问题根源

在steady_timer t的异步等待回调中创建的print pp(io)是局部变量,回调函数执行完毕后,该变量会立即被销毁。此时pp内部的定时器还没来得及触发第一次回调(或回调刚触发就因对象析构失效),因此只会调用析构函数输出Last num 0,无法执行后续计数逻辑。

而第一个print p(io)位于main函数作用域,生命周期持续到io.run()执行结束后,因此能正常完成5次计数输出。

解决方案

需要延长第二个print对象的生命周期,确保其在定时器完成所有回调前不会被销毁。推荐使用std::shared_ptr结合std::enable_shared_from_this来管理对象生命周期,让异步回调持有对象的引用,避免提前析构。

修正后的代码

#include <iostream>
#include <functional>
#include <memory>
#include <boost/asio.hpp>

class print : public std::enable_shared_from_this<print> {
public:
    print(boost::asio::io_context& io) : timer_(io, boost::asio::chrono::seconds(1)), count_(0) {
        timer_.async_wait(std::bind(&print::printer, shared_from_this()));
    }

    void printer() {
        if (count_ < 5) {
            std::cout << count_ << "\n";
            ++count_;

            timer_.expires_at(timer_.expiry() + boost::asio::chrono::seconds(1));
            timer_.async_wait(std::bind(&print::printer, shared_from_this()));
        }
    }

    ~print() {
        std::cout << "Last num " << count_ << "\n";
    }
private:
    boost::asio::steady_timer timer_;
    int count_;
};

int main() {
    boost::asio::io_context io;
    
    print p(io);

    // 设置0.5秒延迟,符合需求
    boost::asio::steady_timer t(io, boost::asio::chrono::milliseconds(500));
    t.async_wait([&io](const boost::system::error_code& ec) {
        if (!ec) {
            // 用shared_ptr管理对象,延长生命周期
            auto pp = std::make_shared<print>(io);
        }
    });

    io.run();   
}

关键修正点

  1. 继承enable_shared_from_this:让print类继承std::enable_shared_from_this<print>,这样可以在成员函数中通过shared_from_this()获取对象的shared_ptr,确保每次异步回调都持有对象的引用,避免对象被提前销毁。
  2. 用shared_ptr创建对象:在回调中使用std::make_shared<print>(io)创建对象,shared_ptr会自动管理生命周期,直到所有回调执行完毕后才销毁对象。
  3. 调整延迟时间:将第二个定时器的延迟从2秒改为500毫秒,满足“第二个定时器在第一个启动0.5秒后开始运行”的需求。

预期输出

修正后两个定时器会交替输出计数,直到各自完成5次循环,最终输出析构信息:

0
1
0
2
1
3
2
4
3
Last num 5
4
Last num 5

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:05:05