Pregunta

Tengo una máquina que utiliza un cliente NTP para sincronizar la hora de Internet, por lo que el reloj del sistema debería ser bastante preciso.

Tengo una aplicación que estoy desarrollando que registra datos en tiempo real, los procesa y luego los transmite.Lo que me gustaría hacer ahora es generar esos datos cada N milisegundos alineados con el reloj del sistema.Entonces, por ejemplo, si quisiera hacer intervalos de 20 ms, mis salidas deberían ser algo como esto:

13:15:05:000
13:15:05:020
13:15:05:040
13:15:05:060

He visto sugerencias para usar la clase de cronómetro, pero eso solo mide períodos de tiempo en lugar de buscar marcas de tiempo específicas.El código para hacer esto se ejecuta en su propio hilo, por lo que debería ser un problema si necesito realizar algunas llamadas relativamente bloqueantes.

Cualquier sugerencia sobre cómo lograr esto con una precisión razonable (cerca o mejor que 1 ms sería buena) será bien recibida.

¿Fue útil?

Solución

No sé lo bien que juega con C ++ / CLR pero probablemente querrá buscar en la multimedia temporizadores , España Windows no es realmente en tiempo real, pero esto es lo más cerca que llegue

Otros consejos

Se puede obtener un sello de tiempo bastante exacto de timeGetTime () cuando se reduce el período de tiempo. Usted sólo necesita un poco de trabajo para obtener su valor de retorno convertir en una hora del reloj. Este ejemplo de código C # muestra el enfoque:

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        timeBeginPeriod(1);
        uint tick0 = timeGetTime();
        var startDate = DateTime.Now;
        uint tick1 = tick0;
        for (int ix = 0; ix < 20; ++ix) {
            uint tick2 = 0;
            do {  // Burn 20 msec
                tick2 = timeGetTime();
            } while (tick2 - tick1 < 20);
            var currDate = startDate.Add(new TimeSpan((tick2 - tick0) * 10000));
            Console.WriteLine(currDate.ToString("HH:mm:ss:ffff"));
            tick1 = tick2;
        }
        timeEndPeriod(1);
        Console.ReadLine();
    }
    [DllImport("winmm.dll")]
    private static extern int timeBeginPeriod(int period);
    [DllImport("winmm.dll")]
    private static extern int timeEndPeriod(int period);
    [DllImport("winmm.dll")]
    private static extern uint timeGetTime();
}

En el segundo pensamiento, esto es sólo la medición. Para conseguir una acción realizada periódicamente, usted tiene que utilizar timeSetEvent (). Como siempre y cuando utilice timeBeginPeriod (), se puede obtener el periodo de devolución de llamada muy cerca de 1 milisegundo. Una sutileza es que va a compensar automáticamente cuando la devolución de llamada anterior era tarde por cualquier motivo.

Su mejor opción es el uso de línea de montaje y la redacción de este trozo de código como un controlador de dispositivo.

De esa manera:

  • Usted tiene control sobre la instrucción recuento
  • Su aplicación tendrá prioridad de ejecución

En última instancia, no puede garantizar lo que desea porque el sistema operativo tiene que cumplir con las solicitudes de otros procesos para ejecutarse, lo que significa que siempre puede haber algo más ocupado exactamente en el momento en que desea que se ejecute su proceso.Pero puedes mejorar las cosas usando timeBeginPeriod para que sea más probable que su proceso pueda cambiarse de manera oportuna, y tal vez sea astuto al esperar entre iteraciones, por ejemplo.durmiendo la mayor parte del tiempo, pero no todo, y luego usando un circuito ocupado durante el resto.

Trate de hacer esto de dos hilos. En un hilo, algo así como el uso este para consultar un contador de tiempo de alta precisión en un bucle. Cuando se detecta una marca de tiempo que se alinea a (o está razonablemente cerca de) un límite de 20 ms, envía una señal a su hilo de salida del registro junto con la fecha y hora de su uso. Su hilo de salida del registro se limitaría a esperar una señal, y luego agarrar el pasado-en fecha y hora de salida y lo que sea necesario. Manteniendo los dos en hilos separados se asegurará de que su hilo de salida del registro no interfiere con el temporizador (esto está emulando esencialmente una interrupción del temporizador de hardware, lo que sería la forma en que lo haría en una plataforma embebida).

CreateWaitableTimer / SetWaitableTimer y un subproceso de prioridad alta debe tener una precisión de aproximadamente 1 ms. No sé por qué el campo de milisegundos en su salida de ejemplo tiene cuatro dígitos, el valor máximo es 999 (desde 1000 ms = 1 segundo).

Dado que como usted ha dicho, esto no tiene que ser perfecto, hay algunas cosas que se puede hacer.

Por lo que yo sé, no existe un temporizador que se sincroniza con un tiempo específico. Por lo que tendrá que calcular su próxima vez y programar el temporizador para ese momento específico. Si el temporizador sólo tiene soporte delta, a continuación, que se calcula con facilidad, pero añade más errores ya que el que fácilmente podría ser expulsado de la CPU entre el momento de calcular el delta y el tiempo se introduce el temporizador en el núcleo.

Como ya se ha señalado, Windows no es un sistema operativo de tiempo real. Por lo que debe suponer que, incluso si se programa un temporizador para bajamos en ": 0010", su código no podría incluso ejecutar hasta bien después de ese tiempo (por ejemplo, ": 0540"). Siempre y cuando se maneja adecuadamente estas cuestiones, las cosas van a ser "ok".

20 ms es aproximadamente la longitud de un segmento de tiempo en Windows. No hay manera de golpear 1ms tipo de horarios en las ventanas de forma fiable sin algún tipo de RT en añadir como Intime. En las ventanas adecuada Creo que sus opciones son WaitForSingleObject, SleepEx, y un bucle ocupado.

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