Question

J'ai essayé d'utiliser le boost date_timer dans cette application de test simple, mais j'ai eu quelques problèmes.L'objectif est que le minuteur se déclenche toutes les 45 millisecondes à l'aide de la fonction membre expires_at() du deadline_timer.(J'ai besoin d'un temps absolu, donc je ne considère pas expires_from_now(). Je ne suis pas non plus préoccupé par la dérive pour le moment).Quand je lance le programme, wait() n'attend pas 45 ms!Pourtant, aucune erreur n'est signalée.Est-ce que j'utilise la bibliothèque de manière incorrecte?

Exemple de programme:

#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;
}
Était-ce utile?

La solution

Vous mélangez l'heure locale et l'heure système.L'heure à laquelle asio compare votre heure locale correspond probablement à un certain nombre d'heures après l'heure à laquelle vous souhaitez que votre date limite soit fixée afin que l'attente revienne immédiatement (selon l'endroit où vous habitez; ce même code peut également attendre plusieurs heures).Pour éviter ce point de confusion, les temps absolus doivent être dérivés de 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; 
}

Cela devrait fonctionner pour vous dans ce cas.

Autres conseils

Vous mélangez des méthodes asynchrones io_service::run avec des méthodes synchrones deadline_timer::wait. Cela ne fonctionnera pas. Utilisez soit deadline_timer::async_wait avec io_service::run, soit ignorez le io_service::run et utilisez simplement deadline_timer::wait. Vous n'avez pas non plus besoin d'un thread pour appeler io_service:run si vous suivez la route asynchrone, un thread fera très bien l'affaire. Les deux concepts sont expliqués en détail dans la section Compétences de base du Tutoriel 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;
}

Notez que vous devrez donner un peu de travail pour votre io_service au service avant d'appeler run(). Dans cet exemple, async_wait est ce travail.

Potentiellement sans rapport: 45 ms est un petit delta. D'après mon expérience, le temps le plus court pour un gestionnaire de traverser la file d'attente du réacteur Asio epoll est d'environ 30 ms, cela peut être considérablement plus long à des charges plus élevées. Bien que tout dépende en grande partie de votre application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top