C++技术问询:如何在不休眠或冻结线程的情况下等待指定时长并执行连续函数调用
在C++中实现非阻塞延迟调用的方案
嘿,咱们来搞定这个问题!你需要先调用一次Do_Something(),然后等待1.70秒再调用一次,同时还得保证线程不会被冻结,能正常处理其他任务对吧?下面给你两种基于C++标准库的靠谱实现方案:
方案一:使用异步线程实现延迟(简单直观)
这种方案通过启动一个独立的异步线程来处理延迟逻辑,主线程完全不受影响,可以继续处理自己的任务。
#include <iostream> #include <future> #include <chrono> #include <thread> // 示例的Do_Something函数 void Do_Something() { auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); std::cout << "Do_Something 被调用,当前时间:" << ctime(&now); } int main() { float s = 1.70f; // 第一次调用目标函数 Do_Something(); // 启动异步任务,负责延迟后再次调用 auto delay_task = std::async(std::launch::async, [s]() { // 将浮点型秒数转换为chrono支持的时长类型 auto delay_duration = std::chrono::duration<float, std::ratio<1>>(s); // 异步线程休眠指定时长(不会影响主线程) std::this_thread::sleep_for(delay_duration); // 时间到后再次调用 Do_Something(); }); // 主线程在这里处理其他任务,完全不会被阻塞 std::cout << "主线程正在处理其他工作..." << std::endl; for (int i = 0; i < 6; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); std::cout << "主线程工作中:第 " << i+1 << " 步" << std::endl; } // 可选:等待异步任务完成(如果需要确保程序结束前延迟调用执行完毕) delay_task.get(); return 0; }
方案说明
std::async(std::launch::async)会创建一个新线程来执行lambda中的逻辑,主线程立刻返回继续执行。std::chrono::duration<float>可以直接接收浮点型的秒数,完美适配你定义的float s = 1.70。- 异步线程的休眠不会影响主线程,主线程可以正常处理任何其他业务逻辑。
方案二:使用条件变量的定时等待(适合单线程事件循环)
如果你的程序是单线程事件循环架构,不想额外创建线程,可以用这种方式,它能在等待过程中响应其他事件,不会让线程完全停滞。
#include <iostream> #include <chrono> #include <mutex> #include <condition_variable> #include <thread> void Do_Something() { auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); std::cout << "Do_Something 被调用,当前时间:" << ctime(&now); } int main() { float s = 1.70f; Do_Something(); std::mutex mtx; std::condition_variable cv; bool delay_completed = false; // 计算延迟结束的时间点 auto wake_up_time = std::chrono::system_clock::now() + std::chrono::duration<float>(s); // 单线程事件循环 while (!delay_completed) { std::unique_lock<std::mutex> lock(mtx); // 等待直到超时或者被其他事件唤醒 if (cv.wait_until(lock, wake_up_time) == std::cv_status::timeout) { // 超时触发,执行第二次调用 Do_Something(); delay_completed = true; } // 在这里处理其他事件或任务逻辑 std::cout << "主线程正在处理其他事件..." << std::endl; // 模拟其他任务的短时间处理 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } return 0; }
方案说明
std::condition_variable::wait_until会让线程进入等待状态,但同时会释放互斥锁,允许其他逻辑(如果有的话)唤醒线程处理紧急任务。- 当到达指定时间点时,函数会返回
std::cv_status::timeout,此时我们就可以执行第二次Do_Something()调用。 - 整个过程中线程不会被完全冻结,只要有其他事件唤醒条件变量,就能立刻处理对应任务。
额外注意事项
- 两种方案都基于C11及以上标准,确保你的编译器支持C11或更高版本。
- 如果需要更精确的时间控制,
std::chrono库还支持纳秒级别的时长类型,可根据需求调整。
内容的提问来源于stack exchange,提问作者CodeX
相关产品推荐
相关产品推荐

