实现带Start/Stop功能的C++回调定时器求助
带停止功能的异步回调定时器实现
需要实现一个定时器类,核心需求如下:
- 启动异步线程,在指定超时时间后执行预设的回调函数
- 支持在超时前主动停止定时器,此时回调函数不会被执行
以下是完善后的实现代码:
#include <iostream> #include <chrono> #include <thread> #include <functional> #include <mutex> #include <condition_variable> #include <atomic> class Timer { public: Timer(size_t time_ms, const std::function<void(void)>& callback) : time(std::chrono::milliseconds(time_ms)), callback(callback) {} ~Timer() { stop(); if (started) { wait_thread.join(); started = false; } } void stop() { stopped.store(true); cv.notify_one(); } void start() { if (!started) { stopped.store(false); started = true; wait_thread = std::thread{ [this]() { wait_then_call(); } }; } else { std::cout << "Thread " << wait_thread.get_id() << " 已启动!" << std::endl; } } private: void wait_then_call() { std::unique_lock<std::mutex> lck(mtx); std::cout << "Thread " << wait_thread.get_id() << " 将在 " << time.count() / 1000 << " 秒后执行回调" << std::endl; // 等待超时或被唤醒 cv.wait_for(lck, time, [this](){ return stopped.load(); }); // 只有未被停止时才执行回调 if (!stopped.load()) { callback(); } else { std::cout << "Thread " << wait_thread.get_id() << " 已取消,回调不执行" << std::endl; } } std::mutex mtx; std::condition_variable cv{}; std::chrono::milliseconds time; std::function<void(void)> callback; std::thread wait_thread; bool started = false; std::atomic<bool> stopped = false; // 原子变量保证线程安全 };
关键改动说明
- 添加
std::atomic<bool> stopped:原子变量确保多线程环境下修改和读取的线程安全性,避免数据竞争 stop()方法:设置停止标志并唤醒等待中的线程,让定时器线程能立即退出等待逻辑wait_then_call()方法:使用wait_for的第三个参数(谓词),等待超时或停止标志被设置;最后检查停止标志,仅当未停止时执行回调- 析构函数优化:先调用
stop()确保线程能及时退出,再join线程,避免程序退出时的资源泄漏
测试示例
int main() { auto f = []() {std::cout << "\n执行回调函数!" << std::endl; }; Timer t1{ 3000, f }; t1.start(); Timer t2{ 10000, f }; t2.start(); // 主线程模拟其他任务,2秒后停止t2 std::this_thread::sleep_for(std::chrono::seconds(2)); t2.stop(); // 等待t1执行完毕 std::this_thread::sleep_for(std::chrono::seconds(2)); return 0; }
运行结果示例:
Thread 140702662397696 将在 3 秒后执行回调 Thread 140702653994880 将在 10 秒后执行回调 Thread 140702653994880 已取消,回调不执行 执行回调函数!
内容的提问来源于stack exchange,提问作者Dominic Sesto
相关产品推荐
相关产品推荐

