从boost::threads到boost::asio定时器

From boost::threads to boost::asio timers

本文关键字:boost 定时器 asio threads      更新时间:2023-10-16

在我的项目中,每个类对象都有自己的线程,内部有无限循环(while(1)),其中执行特定的对象函数。我正试图改变这一点,以便每个对象都能与计时器异步执行其功能。

基本上,这就是它与线程和无限循环的工作方式:

class obj
{
    public:
          obj();
          ~obj();
         //custom functions and variables
        int x;
        int obj_action;
        move();
        wait();
}
obj()
{
     obj_action=1;
     //when constructing object, make its thread with infinite while cycle
     boost::thread make_thread(boost::bind(&obj::obj_engine,this));
}
void obj::obj_engine()
{
     while(true)
     {
       if (obj_action==1){move();}
       else if (obj_action==2){wait();}
       Sleep(1);
     }
}
void obj::move()
{
      x++;
      obj_action==2;
}

void obj::wait()
{
      Sleep(5000);
      obj_action==1;
}

这个例子展示了obj类,它有构造函数、析构函数、变量对和函数对。当构造一个对象(obj())时,就会产生线程。线程包含一个函数"obj_engine",该函数具有无限循环(while(true))。循环中有两个函数:1.wait()-使线程睡眠5秒。2.walk()-简单地x+1这两个函数在结束后通过定义objaction相互切换。

现在我想把它改为,当构造和对象时,将执行异步move()函数,在执行move(。所以我不需要使用任何线程。

我希望这样的结果:

//constructing
obj()
{
       asynchronous(walk());
}
walk()
{
    x++
    asynchronous(wait());
}
wait()
{
    Sleep(5000);
    asynchronous(walk());
}

我听说你可以用boost::asio定时器做到这一点,但我真的不知道怎么做。如果有人能教我怎么做,我将不胜感激。

开始:

#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind.hpp>
#include <iostream>

class obj {
public:
    obj() : x_(0), t_(io_service_, boost::posix_time::seconds(5)) {
        t_.async_wait(boost::bind(&obj::move, this));
        io_service_.run();
    }
    void move() {
        x_++;
        std::cout << x_ << std::endl;
        t_.expires_at(t_.expires_at() + boost::posix_time::seconds(5));
        t_.async_wait(boost::bind(&obj::move, this));
    }
private:
    int x_;
    boost::asio::io_service io_service_;
    boost::asio::deadline_timer t_;
};
int main(int, char**) {
    obj a;
    while(true);
}

基本上,asio教程涵盖了您所需要的一切:本教程向您展示了如何使用异步计时器,本教程向你展示了如何重置计时器。

更新:

请使用上面的源代码,而不是我最初的源代码-由于io_service_.run()的重复调用,每个move调用都会在另一个线程中调用,一段时间后你的应用程序会因此崩溃。上面的代码修复了这个问题,并通过这样做去掉了wait函数。

借用nijansen的例子,我已经拼凑出了一些应该与您想要的更相似的东西(我认为)。

这里的关键是io_service应该在所有对象的调度之间共享。通常每个线程有一个io_service,但也可以使用更复杂的方案。只要io_service上安排了工作(挂起超时或等待套接字),io_service::run就会运行。当没有安排更多的工作时,它只是返回。

您可能对io_service::post感兴趣,它是在"活动对象"之间发送消息的一种方式(即使它们在不同的io_services和不同的线程下运行,它也能工作)。您可能希望查看boost::bind,也可能查看boost::signals

#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind.hpp>
#include <iostream>
namespace asio = boost::asio;
class obj {
public:
    obj(asio::io_service& ioSvc)
      : x_(0), t_(ioSvc)
    {
        schedule_in(5);
    }
    void schedule_in(int seconds) {
        t_.expires_from_now(boost::posix_time::seconds(3));
        t_.async_wait(boost::bind(&obj::move, this));
    }
    void move() {
        x_++;
        std::cout << x_ << std::endl;
        schedule_in(5);
    }
private:
    int x_;
    boost::asio::deadline_timer t_;
};
int main(int, char**) {
    boost::asio::io_service io_service;
    obj a(io_service);
    obj b(io_service);
    obj c(io_service);
    io_service.run();
}