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

带reset功能的C++ Timer类问题:函数无延迟执行及reset失效

修复带Reset功能的Timer类问题

问题根源分析

  1. start后回调立即执行:原实现大概率在启动时直接调用了回调函数,而非通过延迟逻辑触发;或者定时器的等待逻辑错误(比如等待时长设为0)。
  2. reset方法无效:原实现未正确终止当前等待的定时器任务,也未重新启动新的延迟周期,导致原定时器仍会按原时间触发回调。

修复后的Timer类实现

#include <iostream>
#include <functional>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>

class Timer {
public:
    Timer(std::function<void()> func, std::chrono::milliseconds interval)
        : func_(std::move(func)), interval_(interval), running_(false), reset_flag_(false) {}

    ~Timer() {
        stop();
    }

    void start() {
        std::lock_guard<std::mutex> lock(mtx_);
        if (running_) return;
        running_ = true;
        thread_ = std::thread(&Timer::timer_loop, this);
    }

    void stop() {
        std::lock_guard<std::mutex> lock(mtx_);
        running_ = false;
        reset_flag_ = true;
        cv_.notify_one();
        if (thread_.joinable()) {
            thread_.join();
        }
    }

    void reset() {
        std::lock_guard<std::mutex> lock(mtx_);
        reset_flag_ = true;
        cv_.notify_one();
    }

private:
    void timer_loop() {
        while (running_) {
            std::unique_lock<std::mutex> lock(mtx_);
            // 等待指定时长,或被reset/stop唤醒
            auto wait_status = cv_.wait_for(lock, interval_, [this]() {
                return !running_ || reset_flag_;
            });

            if (!running_) break;

            if (reset_flag_) {
                reset_flag_ = false;
                continue; // 重置后重新开始计时
            }

            // 等待超时,触发回调
            if (wait_status == std::cv_status::timeout) {
                func_();
            }
        }
    }

    std::function<void()> func_;
    std::chrono::milliseconds interval_;
    std::thread thread_;
    std::mutex mtx_;
    std::condition_variable cv_;
    bool running_;
    bool reset_flag_;
};

关键修复点说明

  • 解决立即执行问题:通过std::condition_variable::wait_for实现精准延迟,仅当等待周期结束(超时)时才执行回调函数,启动阶段不会直接调用。
  • 解决reset无效问题:调用reset()时设置重置标志并唤醒等待线程,线程被唤醒后会重置计时周期,重新开始等待,从而推迟回调的执行时间。

测试验证代码

int main() {
    Timer timer([](){ std::cout << "reached!" << std::endl; }, std::chrono::seconds(5));
    timer.start();
    
    // 每秒重置一次,理论上永远不会触发回调
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        timer.reset();
        std::cout << "reset timer" << std::endl;
    }
    
    timer.stop();
    return 0;
}

运行该代码后,只会持续输出reset timer,不会出现reached!,符合预期。

内容的提问来源于stack exchange,提问作者Babak.Abad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:50:26