gpt4 book ai didi

c++ - 使用 std 或 boost 库的 C++ 中的 Qtimer 等效于什么?

转载 作者:太空狗 更新时间:2023-10-29 20:34:02 24 4
gpt4 key购买 nike

我必须每 5 秒执行一次任务,直到程序退出。我不想在这里使用线程。

在 QT 中我可以这样做

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);

但我如何使用 std 或 boost 库在 C++ 中执行此操作?

谢谢

最佳答案

我必须假设,“我不想使用线程”是指您不想在每次需要计时器时都在自己的代码中创建线程。那是因为在没有线程的情况下这样做实际上非常困难。

假设使用 C++11,您实际上可以使用 核心语言(不需要 Boost 或任何其他东西)并使用一个单独的类来处理线程,这样您就可以在您的自己的代码是这样的(例如,用垃圾邮件骚扰你的前伴侣,一个相当可疑的用例):

    Periodic spamEx(std::chrono::seconds(60), SendEmaiToEx);

下面的完整程序,用g++ -std=c++11 -o periodic periodic.cpp -lpthread编译,将每秒运行一个周期性回调函数,持续五秒(a) :

#include <thread>
#include <chrono>
#include <functional>
#include <atomic>

// Not needed if you take couts out of Periodic class.
#include <iostream>

class Periodic {
public:
explicit Periodic(
const std::chrono::milliseconds &period,
const std::function<void ()> &func
)
: m_period(period)
, m_func(func)
, m_inFlight(true)
{
std::cout << "Constructing periodic" << std::endl;
m_thread = std::thread([this] {
while (m_inFlight) {
std::this_thread::sleep_for(m_period);
if (m _inFlight) {
m_func();
}
}
});
}

~Periodic() {
std::cout << "Destructed periodic" << std::endl;
m_inFlight = false;
m_thread.join();
std::cout << "Destructed periodic" << std::endl;
}

private:
std::chrono::milliseconds m_period;
std::function<void ()> m_func;
std::atomic<bool> m_inFlight;
std::thread m_thread;
};

// This is a test driver, the "meat" is above this.

#include <iostream>

void callback() {
static int counter = 0;
std::cout << "Callback " << ++counter << std::endl;
}

int main() {
std::cout << "Starting main" << std::endl;
Periodic p(std::chrono::seconds(1), callback);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Ending main" << std::endl;
}

当您创建一个Periodic 实例时,它会保存相关信息并启动一个线程来完成这项工作。线程(lambda)只是一个循环,它首先延迟一段时间然后调用您的函数。它会继续这样做,直到析构函数指示它应该停止。

输出如预期的那样:

Starting main
Constructing periodic
Callback 1
Callback 2
Callback 3
Callback 4
Ending main
Destructed periodic

(a) 请注意,上面给出的时间实际上是从一个回调结束到下一个回调开始的时间,不是从开始到开始的时间(我称之为真正的周期时间)。如果您的回调与期间相比足够快,则差异有望不明显。

此外,线程无论如何都会延迟,因此析构函数在返回之前可能会延迟一个完整的周期。

如果您确实需要一个开始到开始的周期和快速清理,您可以改用以下线程。它通过计算回调的持续时间并仅延迟该周期的剩余(或者如果回调使用了整个周期则根本不延迟)来实现真正的开始到开始计时。

它还使用较小的 sleep ,以便快速清理。线程函数将是:

m_thread = std::thread([this] {
// Ensure we wait the initial period, then start loop.

auto lastCallback = std::chrono::steady_clock::now();
while (m_inFlight) {
// Small delay, then get current time.

std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto timeNow = std::chrono::steady_clock::now();

// Only callback if still active and current period has expired.

if (m_inFlight && timeNow - lastCallback >= m_period) {
// Start new period and call callback.

lastCallback = timeNow;
m_func();
}
}
});

请注意,如果您的回调花费的时间比周期长,您基本上会几乎连续调用它(至少会有 100 毫秒的间隔)。

关于c++ - 使用 std 或 boost 库的 C++ 中的 Qtimer 等效于什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51549454/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com