повышение deadline_timer не ждет - PullRequest
3 голосов
/ 22 марта 2011

Я пытался использовать boost deadline_timer в этом простом тестовом приложении, но у меня возникли некоторые проблемы. Цель состоит в том, чтобы таймер срабатывал каждые 45 миллисекунд, используя функцию-член expires_at() из deadline_timer. (Мне нужно абсолютное время, поэтому я не рассматриваю expires_from_now(). Я также не беспокоюсь о дрейфе в данный момент). Когда я запускаю программу, wait() не ждет 45 мс! Пока не сообщается об ошибках. Я как-то неправильно использую библиотеку?

Пример программы:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace std;

int main()
{
        boost::asio::io_service Service;
        boost::shared_ptr<boost::thread> Thread;
        boost::asio::io_service::work RunForever(Service);
        Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
        boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));

        while(1)
        {
                boost::posix_time::time_duration Duration;
                Duration = boost::posix_time::microseconds(45000);
                boost::posix_time::ptime Start = boost::posix_time::microsec_clock::local_time();
                boost::posix_time::ptime Deadline = Start + Duration;
                boost::system::error_code Error;
                size_t Result = Timer->expires_at(Deadline, Error);
                cout << Result << ' ' << Error << ' ';
                Timer->wait(Error);
                cout << Error << ' ';
                boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
                (cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
        }
        return 0;
}

Ответы [ 2 ]

7 голосов
/ 22 марта 2011

Вы смешиваете местное время с системным временем. Время, с которым asio сравнивает ваше местное время, скорее всего, составляет несколько часов после того времени, когда вы хотите, чтобы ваш конечный срок был установлен так, чтобы ожидание немедленно возвращалось (в зависимости от того, где вы живете; этот же код может также ждать несколько часов). Чтобы избежать этой путаницы, абсолютные времена должны быть получены из asio :: time_traits.

#include <boost/asio.hpp>
#include <boost/asio/time_traits.hpp>
#include <boost/thread.hpp> 
#include <boost/bind.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <iostream> 
using namespace std;

typedef boost::asio::time_traits<boost::posix_time::ptime> time_traits_t;  
int main() {         
    boost::asio::io_service Service;         
    boost::shared_ptr<boost::thread> Thread;         
    boost::asio::io_service::work RunForever(Service);         
    Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
    boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));          
    while(1)         
    {                 
        boost::posix_time::time_duration Duration;
        Duration = boost::posix_time::microseconds(45000);
        boost::posix_time::ptime Start = time_traits_t::now();
        boost::posix_time::ptime Deadline = Start + Duration;
        boost::system::error_code Error;
        size_t Result = Timer->expires_at(Deadline, Error);
        cout << Result << ' ' << Error << ' ';
        Timer->wait(Error);
        cout << Error << ' ';
        boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
        (cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
     }         
    return 0; 
}

Это должно сработать для вас в этом случае.

4 голосов
/ 22 марта 2011

Вы смешиваете асинхронные методы io_service::run с синхронными методами deadline_timer::wait.Это не будет работать.Либо используйте deadline_timer::async_wait с io_service::run, либо пропустите io_service::run и просто используйте deadline_timer::wait.Вам также не нужен поток для вызова io_service:run, если вы идете по асинхронному маршруту, один поток будет работать нормально.Обе концепции подробно объясняются в разделе Базовые навыки учебного пособия Asio .

void print(const boost::system::error_code& /*e*/)
{
  std::cout << "Hello, world!\n";
}

int main()
{
  boost::asio::io_service io;

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
  t.async_wait(print);
  io.run();

  return 0;
}

Обратите внимание, что вам понадобится немного поработать для io_serviceна обслуживание до вызова run().В этом примере async_wait - это работа.

Потенциально не связана: 45 мс - это довольно маленькая дельта.По моему опыту, наименьшее время для любого обработчика, чтобы пройти через очередь реактора Asio epoll, составляет около 30 мс, это может быть значительно больше при более высоких нагрузках.Хотя все это в значительной степени зависит от вашего приложения.

...