C++ 中的周期性定时器间隔
periodic timer intervals in C++
我正在将代码从 C# 转换为 C++。我想每隔一段时间调用一个函数。
我在 C# 中的原始函数是:
private void Init_timerGetData()
{
timerGetData = new Timer();
timerGetData.Interval = 5;
timerGetData.Tick += new EventHandler(ReadData_Tick);
}
private void ReadData_Tick(object sender, EventArgs e)
{...}
如何用 C++ 重写此函数以获得相同的功能?
您可以使用 class 启动自己的 thread
来调用。这是我使用的一个简单的方法,它将在每个周期调用直到 class 的析构函数运行。您可以调整实现的细节以实现您想要的大部分内容:
#include <atomic>
#include <chrono>
#include <functional>
#include <thread>
class call_every
{
std::function<void()> f_;
std::chrono::system_clock::duration d_;
std::chrono::system_clock::time_point run_now_;
std::atomic_bool quit_;
std::thread thr_;
public:
~call_every()
{
quit_ = true;
thr_.join();
}
template <class F>
explicit call_every(F f, std::chrono::system_clock::duration d)
: f_{std::move(f)}
, d_{d}
, run_now_{std::chrono::system_clock::now()}
, quit_{false}
, thr_{&call_every::run, this}
{}
private:
void run()
{
while (!quit_)
{
f_();
run_now_ += d_;
std::this_thread::sleep_until(run_now_);
}
}
};
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
call_every x{[]{cout << "Hi" << endl;}, 5s};
this_thread::sleep_for(15s);
}
$ a.out
Hi
Hi
Hi
Hi
$
这是上面的一个变体,它对 quit_
命令的响应更快。它不是在持续时间内无条件休眠,而是使用 condition_variable
和 wait_until
,~call_every()
可以在持续时间超时之前中断。如果这很重要,这可以确保更及时地关闭。
#include <chrono>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
class call_every
{
std::mutex mut_;
std::condition_variable cv_;
std::function<void()> f_;
std::chrono::system_clock::duration d_;
std::chrono::system_clock::time_point run_now_;
bool quit_;
std::thread thr_;
public:
~call_every()
{
{
std::lock_guard lock{mut_};
quit_ = true;
}
cv_.notify_one();
thr_.join();
}
template <class F>
explicit call_every(F f, std::chrono::system_clock::duration d)
: f_{std::move(f)}
, d_{d}
, run_now_{std::chrono::system_clock::now()}
, quit_{false}
, thr_{&call_every::run, this}
{
}
private:
void run()
{
while (true)
{
f_();
run_now_ += d_;
std::unique_lock lock{mut_};
if (cv_.wait_until(lock, run_now_, [this]() {return quit_;}))
break;
}
}
};
我正在将代码从 C# 转换为 C++。我想每隔一段时间调用一个函数。 我在 C# 中的原始函数是:
private void Init_timerGetData()
{
timerGetData = new Timer();
timerGetData.Interval = 5;
timerGetData.Tick += new EventHandler(ReadData_Tick);
}
private void ReadData_Tick(object sender, EventArgs e)
{...}
如何用 C++ 重写此函数以获得相同的功能?
您可以使用 class 启动自己的 thread
来调用。这是我使用的一个简单的方法,它将在每个周期调用直到 class 的析构函数运行。您可以调整实现的细节以实现您想要的大部分内容:
#include <atomic>
#include <chrono>
#include <functional>
#include <thread>
class call_every
{
std::function<void()> f_;
std::chrono::system_clock::duration d_;
std::chrono::system_clock::time_point run_now_;
std::atomic_bool quit_;
std::thread thr_;
public:
~call_every()
{
quit_ = true;
thr_.join();
}
template <class F>
explicit call_every(F f, std::chrono::system_clock::duration d)
: f_{std::move(f)}
, d_{d}
, run_now_{std::chrono::system_clock::now()}
, quit_{false}
, thr_{&call_every::run, this}
{}
private:
void run()
{
while (!quit_)
{
f_();
run_now_ += d_;
std::this_thread::sleep_until(run_now_);
}
}
};
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
call_every x{[]{cout << "Hi" << endl;}, 5s};
this_thread::sleep_for(15s);
}
$ a.out
Hi
Hi
Hi
Hi
$
这是上面的一个变体,它对 quit_
命令的响应更快。它不是在持续时间内无条件休眠,而是使用 condition_variable
和 wait_until
,~call_every()
可以在持续时间超时之前中断。如果这很重要,这可以确保更及时地关闭。
#include <chrono>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
class call_every
{
std::mutex mut_;
std::condition_variable cv_;
std::function<void()> f_;
std::chrono::system_clock::duration d_;
std::chrono::system_clock::time_point run_now_;
bool quit_;
std::thread thr_;
public:
~call_every()
{
{
std::lock_guard lock{mut_};
quit_ = true;
}
cv_.notify_one();
thr_.join();
}
template <class F>
explicit call_every(F f, std::chrono::system_clock::duration d)
: f_{std::move(f)}
, d_{d}
, run_now_{std::chrono::system_clock::now()}
, quit_{false}
, thr_{&call_every::run, this}
{
}
private:
void run()
{
while (true)
{
f_();
run_now_ += d_;
std::unique_lock lock{mut_};
if (cv_.wait_until(lock, run_now_, [this]() {return quit_;}))
break;
}
}
};