linux c ++ timer定期回调

时间:2014-03-20 17:02:25

标签: c++ linux timer boost-asio

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

从我发现的内容来看,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可以每25ms更新一次,但图像捕获应该只发生10次时间一秒[100ms期间]作为一项需要大量资源的繁重操作]

也许有一种完全不同的方法会更好?我正在考虑更多的线索,但我担心,如果我尝试编写每一个程序,我最终会得到一碗意大利面,从长远来看,我永远无法管理。

1 个答案:

答案 0 :(得分:1)

如果您希望计时器反复触发,您只需在计时器回调中拨打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();
}

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

例如,如果您有25 ms间隔的定时器A和50 ms间隔的定时器B,则有时会安排两个定时器同时触发。其中一个将首先执行,另一个将等待执行完成,然后自行执行。

如果您确实希望定时器回调花费很长时间,而且您的定时器无法等待其他定时器&#39;回调完成后,您需要运行io_service的其他线程。