Pregunta

Intenté usar Boost Deadline_Timer en esta aplicación de prueba simple, pero tuve algunos problemas. El objetivo es que el temporizador active cada 45 milisegundos utilizando el expires_at() Función miembro del deadline_timer. (Necesito un tiempo absoluto, así que no estoy considerando expires_from_now(). Tampoco estoy preocupado por la deriva en este momento). Cuando ejecuto el programa, wait() ¡No espera 45 ms! Sin embargo, no se informan errores. ¿Estoy usando la biblioteca de alguna manera de alguna manera?

Programa de muestra:

#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;
}
¿Fue útil?

Solución

Estás mezclando la hora local con el tiempo del sistema. El momento en que ASIO compara su hora local es muy probable que sea un número de horas después del tiempo que desea que su fecha límite establezca, por lo que espera devoluciones de inmediato (dependiendo de dónde viva; este mismo código también podría esperar durante varias horas). Para evitar este punto de confusión, los tiempos absolutos deben derivarse 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; 
}

Eso debería funcionar para usted en este caso.

Otros consejos

Estás mezclando métodos asíncronos io_service::run con métodos sincrónicos deadline_timer::wait. Esto no funcionará. Ya sea deadline_timer::async_wait con io_service::run, o omita el io_service::run Y solo usa deadline_timer::wait. Tampoco necesitas un hilo para invocar io_service:run Si sigue la ruta asíncrona, un hilo funcionará bien. Ambos conceptos se explican en detalle en el Habilidades básicas Sección de la Tutorial 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;
}

Nota que deberá dar un trabajo para su io_service al servicio antes de invocar run(). En este ejemplo, async_wait es ese trabajo.

Potencialmente no relacionado: 45ms es un delta bastante pequeño. En mi experiencia, el momento más pequeño para que cualquier manejador atraviese la cola de reactores ASIO Epoll sea de alrededor de 30 ms, esto puede ser considerablemente más largo con cargas más altas. Aunque todo depende en gran medida de su aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top