¿Cómo crear eventos de temporizador usando C ++ 11?

¿Cómo crear eventos de temporizador usando C ++ 11?

Necesito algo como: “Llámame después de 1 segundo a partir de ahora”.

¿Hay alguna biblioteca?

Hice una implementación simple de lo que creo que es lo que quiere lograr. Puede usar la clase later con los siguientes argumentos:

  • int (milisegundos para esperar hasta que se ejecute el código)
  • bool (si es verdadero, regresa instantáneamente y ejecuta el código después del tiempo especificado en otro hilo)
  • argumentos variables (exactamente lo que alimentaría a std :: bind )

Puede cambiar std::chrono::milliseconds por std::chrono::nanoseconds o microseconds para una precisión aún mayor y agregar un segundo ciclo int y un ciclo for para especificar cuántas veces ejecutar el código.

Aquí tienes, disfruta:

 #include  #include  #include  #include  class later { public: template  later(int after, bool async, callable&& f, arguments&&... args) { std::function::type()> task(std::bind(std::forward(f), std::forward(args)...)); if (async) { std::thread([after, task]() { std::this_thread::sleep_for(std::chrono::milliseconds(after)); task(); }).detach(); } else { std::this_thread::sleep_for(std::chrono::milliseconds(after)); task(); } } }; void test1(void) { return; } void test2(int a) { printf("%i\n", a); return; } int main() { later later_test1(1000, false, &test1); later later_test2(1000, false, &test2, 101); return 0; } 

Salidas después de dos segundos:

 101 

Si está en Windows, puede usar la función CreateThreadpoolTimer para progtwigr una callback sin tener que preocuparse por la gestión de hilos y sin bloquear el hilo actual.

 template static void __stdcall timer_fired(PTP_CALLBACK_INSTANCE, PVOID context, PTP_TIMER timer) { CloseThreadpoolTimer(timer); std::unique_ptr callable(reinterpret_cast(context)); (*callable)(); } template  void call_after(T callable, long long delayInMs) { auto state = std::make_unique(std::move(callable)); auto timer = CreateThreadpoolTimer(timer_fired, state.get(), nullptr); if (!timer) { throw std::runtime_error("Timer"); } ULARGE_INTEGER due; due.QuadPart = static_cast(-(delayInMs * 10000LL)); FILETIME ft; ft.dwHighDateTime = due.HighPart; ft.dwLowDateTime = due.LowPart; SetThreadpoolTimer(timer, &ft, 0 /*msPeriod*/, 0 /*msWindowLength*/); state.release(); } int main() { auto callback = [] { std::cout << "in callback\n"; }; call_after(callback, 1000); std::cin.get(); } 

Este es el código que tengo hasta ahora:

Estoy usando VC ++ 2012 (sin plantillas variadic)

 //header #include  #include  #include  #include  #include  #include  #include  template class TimerThread { typedef std::chrono::high_resolution_clock clock_t; struct TimerInfo { clock_t::time_point m_TimePoint; T m_User; template  TimerInfo(clock_t::time_point tp, TArg1 && arg1) : m_TimePoint(tp) , m_User(std::forward(arg1)) { } template  TimerInfo(clock_t::time_point tp, TArg1 && arg1, TArg2 && arg2) : m_TimePoint(tp) , m_User(std::forward(arg1), std::forward(arg2)) { } }; std::unique_ptr m_Thread; std::vector m_Timers; std::mutex m_Mutex; std::condition_variable m_Condition; bool m_Sort; bool m_Stop; void TimerLoop() { for (;;) { std::unique_lock lock(m_Mutex); while (!m_Stop && m_Timers.empty()) { m_Condition.wait(lock); } if (m_Stop) { return; } if (m_Sort) { //Sort could be done at insert //but probabily this thread has time to do std::sort(m_Timers.begin(), m_Timers.end(), [](const TimerInfo & ti1, const TimerInfo & ti2) { return ti1.m_TimePoint > ti2.m_TimePoint; }); m_Sort = false; } auto now = clock_t::now(); auto expire = m_Timers.back().m_TimePoint; if (expire > now) //can I take a nap? { auto napTime = expire - now; m_Condition.wait_for(lock, napTime); //check again auto expire = m_Timers.back().m_TimePoint; auto now = clock_t::now(); if (expire <= now) { TimerCall(m_Timers.back().m_User); m_Timers.pop_back(); } } else { TimerCall(m_Timers.back().m_User); m_Timers.pop_back(); } } } template friend void CreateTimer(TimerThread& timerThread, int ms, TArg1 && arg1); template friend void CreateTimer(TimerThread& timerThread, int ms, TArg1 && arg1, TArg2 && arg2); public: TimerThread() : m_Stop(false), m_Sort(false) { m_Thread.reset(new std::thread(std::bind(&TimerThread::TimerLoop, this))); } ~TimerThread() { m_Stop = true; m_Condition.notify_all(); m_Thread->join(); } }; template void CreateTimer(TimerThread& timerThread, int ms, TArg1 && arg1) { { std::unique_lock lock(timerThread.m_Mutex); timerThread.m_Timers.emplace_back(TimerThread::TimerInfo(TimerThread::clock_t::now() + std::chrono::milliseconds(ms), std::forward(arg1))); timerThread.m_Sort = true; } // wake up timerThread.m_Condition.notify_one(); } template void CreateTimer(TimerThread& timerThread, int ms, TArg1 && arg1, TArg2 && arg2) { { std::unique_lock lock(timerThread.m_Mutex); timerThread.m_Timers.emplace_back(TimerThread::TimerInfo(TimerThread::clock_t::now() + std::chrono::milliseconds(ms), std::forward(arg1), std::forward(arg2))); timerThread.m_Sort = true; } // wake up timerThread.m_Condition.notify_one(); } //sample #include  #include  void TimerCall(int i) { std::cout << i << std::endl; } int main() { std::cout << "start" << std::endl; TimerThread timers; CreateTimer(timers, 2000, 1); CreateTimer(timers, 5000, 2); CreateTimer(timers, 100, 3); std::this_thread::sleep_for(std::chrono::seconds(5)); std::cout << "end" << std::endl; } 

La solución asincrónica de Edward:

  • crear un nuevo hilo
  • dormir en ese hilo
  • hacer la tarea en ese hilo

es simple y podría funcionar para usted.

También me gustaría dar una versión más avanzada que tiene estas ventajas:

  • sin sobrecarga de inicio de thread
  • solo un hilo adicional por proceso requerido para manejar todas las tareas progtwigdas

Esto podría ser particularmente útil en proyectos de software grandes donde tiene muchas tareas ejecutadas repetitivamente en su proceso y le preocupa el uso de recursos (hilos) y también la sobrecarga de inicio.

Idea: Tener un hilo de servicio que procese todas las tareas cronometradas registradas. Use boost io_service para eso.

Código similar a: http://www.boost.org/doc/libs/1_65_1/doc/html/boost_asio/tutorial/tuttimer2/src.html

 #include  #include  #include  int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); t.async_wait([](const boost::system::error_code& /*e*/){ printf("Printed after 1s\n"); }); boost::asio::deadline_timer t2(io, boost::posix_time::seconds(1)); t2.async_wait([](const boost::system::error_code& /*e*/){ printf("Printed after 1s\n"); }); // both prints happen at the same time, // but only a single thread is used to handle both timed tasks // - namely the main thread calling io.run(); io.run(); return 0; }