example - ¿Cuál es la mejor manera de salir de un ciclo después de un tiempo transcurrido de 30 ms en C++?
qtimer pyqt5 (9)
El ejemplo del fragmento de código en este enlace hace más o menos lo que desea:
http://www.cplusplus.com/reference/clibrary/ctime/clock/
Adaptado de su ejemplo:
void runwait ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait)
{
/* Do stuff while waiting */
}
}
¿Cuál es la mejor manera de salir de un bucle tan cerca de 30 ms como sea posible en C ++? Incremento de sondeo: microsec_clock? Sondeo QTime? ¿Algo más?
Algo como:
A = now;
for (blah; blah; blah) {
Blah();
if (now - A > 30000)
break;
}
Debería funcionar en Linux, OS X y Windows.
Los cálculos en el ciclo son para actualizar una simulación. Cada 30ms, me gustaría actualizar la ventana gráfica.
Puede considerar simplemente actualizar la ventana gráfica cada N pasos de simulación en lugar de cada K milisegundos. Si esto es (digamos) una aplicación comercial seria, entonces es probable que desee ir a la ruta de múltiples hilos sugerida en otro lugar, pero si (digamos) es para uso personal o de audiencia limitada y lo que realmente le interesa son los detalles de lo que está simulando, entonces cada N pasos es simple, portátil y puede ser lo suficientemente bueno como para seguir adelante.
Según su pregunta, cada 30 ms le gustaría actualizar la ventana gráfica. Escribí una aplicación similar una vez que probaba el hardware cada 500ms para cosas similares. Si bien esto no responde directamente a su pregunta, tengo los siguientes seguimientos:
- ¿Estás seguro de que Blah (), para actualizar la ventana gráfica, puede ejecutar en menos de 30ms en cada instancia?
- Parece que ejecutar Blah () se haría mejor con una devolución de llamada con temporizador.
- Es muy difícil encontrar un objeto de temporizador de biblioteca que presione un intervalo de 30 ms para realizar actualizaciones en un marco gráfico. En Windows XP encontré que el temporizador API Win32 estándar que presiona mensajes de ventana tras la expiración del intervalo del temporizador, incluso en un P4 de 2 GHz, no podía hacer actualizaciones más rápido que un intervalo de 300ms, sin importar qué tan bajo establezca el intervalo de tiempo en el minutero. Si bien hay temporizadores de alto rendimiento disponibles en la API de Win32, tienen muchas restricciones, a saber, que no se puede hacer ningún IPC (como widgets de UI de actualización) en un bucle como el que mencionaste anteriormente.
- Básicamente, el resultado es que debes planear con mucho cuidado cómo quieres que ocurran las actualizaciones. Es posible que necesite utilizar subprocesos y observe cómo desea actualizar la ventana gráfica.
Solo algunas cosas en que pensar. Me sorprendieron cuando trabajé en mi proyecto. Si ya has pensado en estas cosas, ignora mi respuesta: 0).
Si bien esto no responde la pregunta, podría dar otra mirada a la solución. ¿Qué hay de colocar el código de simulación y la interfaz de usuario en diferentes hilos? Si usa Qt, la actualización periódica puede realizarse utilizando un temporizador o incluso QThread :: msleep () . Puede adaptar el ejemplo roscado de Mandelbrot para que se ajuste a sus necesidades.
Si está usando Qt, aquí hay una manera simple de hacerlo:
QTimer* t = new QTimer( parent ) ;
t->setInterval( 30 ) ; // in msec
t->setSingleShot( false ) ;
connect( t, SIGNAL( timeout() ), viewPort, SLOT( redraw() ) ) ;
Deberá especificar viewPort
y viewPort
redraw()
. Luego, inicie el temporizador con t->start()
.
Ver QueryPerformanceCounter y QueryPerformanceFrequency
Los cálculos en el ciclo son para actualizar una simulación. Cada 30ms, me gustaría actualizar la ventana gráfica.
¿Has considerado usar hilos? Lo que describes parece ser el ejemplo perfecto de por qué deberías usar hilos en lugar de temporizadores.
El hilo de proceso principal se ocupa de la interfaz de usuario y tiene un QTimer establecido en 30 ms para actualizarlo. Bloquea un QMutex para tener acceso a los datos, realiza la actualización y libera el mutex.
El segundo hilo (ver QThread ) hace la simulación. Para cada ciclo, bloquea el QMutex, realiza los cálculos y libera el mutex cuando los datos están en un estado estable (adecuado para la actualización de UI).
Con la tendencia creciente en los procesadores multi-core, debería pensar cada vez más en el uso de subprocesos que en el uso de temporizadores. Sus aplicaciones se benefician automáticamente de la mayor potencia (núcleos múltiples) de los nuevos procesadores.
La respuesta breve es: no se puede en general, pero se puede si se está ejecutando en el SO correcto o en el hardware correcto.
Puede obtener CERRAR 30ms en todos los sistemas operativos utilizando una llamada de ensamblaje en sistemas Intel y algo más en otras arquitecturas. Desenterraré la referencia y editaré la respuesta para incluir el código cuando lo encuentre.
El problema es el algoritmo de división en el tiempo y qué tan cerca del final de su segmento de tiempo se encuentra en un sistema operativo multitarea.
En algunos sistemas operativos en tiempo real, hay una llamada al sistema en una biblioteca del sistema que puede hacer, pero no estoy seguro de cuál sería esa llamada.
editar: ¡LOL! Alguien ya ha publicado un fragmento similar en SO: función del temporizador para proporcionar tiempo en nano segundos usando C ++
VonC ha recibido el comentario con el código de ensamblado del temporizador de CPU.
Si necesita trabajar hasta que haya transcurrido un cierto tiempo, la respuesta de docflabby es puntual. Sin embargo, si solo tiene que esperar, sin hacer nada, hasta que haya transcurrido un tiempo especificado, entonces debe usar usleep()