Linux c++ timer周期性回调

linux c++ timer periodic callback

本文关键字:回调 周期性 timer c++ Linux      更新时间:2023-10-16

我试图写一个简单的程序,在其主循环调用不同的函数基于用户输入(这里没有问题),并执行自己的一些动作-那些是基于时间的。由于我想避免潜在的数据访问问题(我不擅长多线程),我试图使用回调来确保每隔几毫秒调用程序的各个自治部分。

从我所发现的,boost::asio看起来像要走的路-但是我不知道这里的正确方法是什么。我已经做了一个简单的代码,工作:

#include <iostream>
#include <boost/asio.hpp>//scheduling
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace std;
void clb(const boost::system::error_code&){
    //  eye.procFrame(&img, true);
    cout << "callback ok" << endl;
}
int main() {
    bool run = true;
    int i =0;
    while(run){
        boost::asio::io_service io;
        boost::asio::deadline_timer t(io, boost::posix_time::seconds(2));
        t.async_wait(clb);
        io.run();
        if(++i>10) run = false;
    }
    cout << "done, i=" << i;
    return 0;
}

我主要关心的是声明——如果我把它们移出while循环,回调只发生一次。是否有一种方法来写回调类似于定时器中断从微控制器?

睡眠不是一个解决方案-它会使程序无响应,并不能保证,程序的部分是根据他们的时间表更新(例如GUI可以每25毫秒更新一次,但图像捕获应该每秒只发生10次[100毫秒周期]作为一个繁重的操作占用大量资源)

也许有一种完全不同的方法会更好?我在考虑更多的线程,但我担心如果我尝试线程化程序的每一部分,我将以一碗意大利面结束,我永远无法长期管理。

如果你想让你的计时器反复触发,你可以在你的计时器回调中调用deadline_timer::expires_from_nowdeadline_timer::async_wait。这将使计时器在每次触发时重新调度自己。

定时器与io_service对象相关联,该对象应该在一个或多个线程上运行。您可以将任意数量的计时器与单个io_service相关联。如果你想让你的定时器串行执行,而不担心并发问题,只需要一个线程运行你的io_service

在这个例子中,我有一个线程运行一个io_service和两个计时器。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/chrono.hpp>
boost::asio::io_service io;
boost::asio::deadline_timer timerA(io);
boost::asio::deadline_timer timerB(io);
boost::chrono::steady_clock::time_point appStart;
void onTimerA(const boost::system::error_code& error)
{
    assert(!error);
    std::cout << "A fired at " << 
        boost::chrono::duration_cast<boost::chrono::milliseconds>
        (boost::chrono::steady_clock::now() - appStart).count() 
        << std::endl;
    timerA.expires_from_now(boost::posix_time::seconds(1));
    timerA.async_wait(onTimerA);
}
void onTimerB(const boost::system::error_code& error)
{
    assert(!error);
    std::cout << "B fired at " << 
        boost::chrono::duration_cast<boost::chrono::milliseconds>
        (boost::chrono::steady_clock::now() - appStart).count() 
        << std::endl;
    timerB.expires_from_now(boost::posix_time::seconds(2));
    timerB.async_wait(onTimerB);
}
int main()
{
     // Prevents io.run() from returning.
    boost::asio::io_service::work work(io);
    appStart = boost::chrono::steady_clock::now();
    timerA.expires_from_now(boost::posix_time::seconds(1));
    timerA.async_wait(onTimerA);
    timerB.expires_from_now(boost::posix_time::seconds(2));
    timerB.async_wait(onTimerB);
    io.run();
}

然而,使用一个线程的缺点是,如果一个计时器回调需要很长时间来执行,它将阻塞其他应该触发的计时器,直到它完成。如果你知道你的计时器回调不会花费很长时间,那么一个线程就可以了。

例如,如果定时器A的间隔为25毫秒,而定时器B的间隔为50毫秒,那么这两个定时器有时会被安排在同一时间触发。其中一个将先执行,另一个将等待该执行完成,然后自己执行。

如果你希望你的计时器回调需要很长时间,你不能让你的计时器等待其他计时器的回调完成,你需要额外的线程运行你的io_service