Domanda

Ho una macchina che utilizza un client NTP per sincronizzare fino a tempo di internet quindi è orologio di sistema dovrebbe essere abbastanza precisa.

Ho un programma che sto sviluppando, che registra i dati in tempo reale, elabora e poi lo passa. Quello che mi piacerebbe fare ora è in uscita che i dati ogni N millisecondi allineati con l'orologio di sistema. Così, per esempio, se volevo fare intervalli di 20ms, i miei oututs dovrebbe essere qualcosa di simile:

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

Ho visto suggerimenti per l'utilizzo della classe cronometro, ma che le misure solo il tempo si estende al contrario di ricerca di specifici timestamp. Il codice per fare questo è in esecuzione in un suo filo, quindi dovrebbe essere un problema se ho bisogno di fare alcune chiamate relativamente blocco.

Qualche suggerimento su come raggiungere questo obiettivo a un ragionevole (vicino o meglio di 1ms precisione sarebbe bello) sarebbero molto ben accetto.

È stato utile?

Soluzione

Non so quanto bene si gioca con C ++ / CLR ma probabilmente vuole guardare timer multimediali ,
Windows non è in realtà in tempo reale, ma questo è il più vicino come si arriva

Altri suggerimenti

È possibile ottenere un abbastanza precisa data e ora di timeGetTime () quando si riduce il periodo di tempo. Avrete solo bisogno di un po 'di lavoro per ottenere il suo valore di ritorno convertito in un tempo di orologio. Questo esempio di codice C # mostra l'approccio:

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();
}

A pensarci bene, questo è solo di misura. Per ottenere un'azione eseguita periodicamente, dovrete usare timeSetEvent (). Finché si utilizza timeBeginPeriod (), è possibile ottenere il periodo di callback abbastanza vicino a 1 msec. Una delicatezza è che compensa automaticamente quando la richiamata precedente era in ritardo per un qualsiasi motivo.

La cosa migliore è usare l'assembly inline e scrivere questo pezzo di codice come un driver di periferica.

In questo modo:

  • Hai il controllo su istruzione di conteggio
  • L'applicazione avrà priorità di esecuzione

In definitiva, non si può garantire ciò che si vuole, perché il sistema operativo deve soddisfare le richieste provenienti da altri processi per l'esecuzione, il che significa che qualcosa può sempre essere occupato esattamente nel momento in cui si desidera che il processo sia in esecuzione. Ma si può migliorare la situazione utilizzando timeBeginPeriod per rendere più probabile che il processo può essere commutato in modo tempestivo, e, forse, di essere furbo con come si attende tra le iterazioni - ad es. dormire per la maggior parte, ma non tutto il tempo e quindi utilizzando un occupato-loop per il resto.

Prova a fare questo in due thread. In un thread, usare qualcosa come questo per interrogare un timer ad alta precisione in un ciclo. Quando si rileva un timestamp che si allinea a (o è ragionevolmente vicino a) un limite di 20ms, inviare un segnale al tuo thread output di registro con il timestamp da usare. Il tuo filo di uscita del registro sarebbe semplicemente attendere un segnale, poi prendete il timestamp e la produzione passata in ciò che è necessario. Mantenendo i due in thread separati farà in modo che il thread di output di registro non interferisce con il timer (questo è essenzialmente emulando un interrupt timer hardware, che sarebbe il modo in cui vorrei farlo su una piattaforma embedded).

CreateWaitableTimer / SetWaitableTimer e un filo ad alta priorità dovrebbe avere una precisione di circa 1 ms. Non so il motivo per cui il campo millisecondo nel tuo esempio di uscita ha quattro cifre, il valore massimo è 999 (fin dal 1000 ms = 1 secondo).

Dal momento che, come lei ha detto, questo non deve essere perfetto, ci sono alcune cose che si può fare.

Per quanto ne so, non esiste un timer che si sincronizza con un tempo specifico. Quindi si dovrà calcolare la prossima volta e programmare il timer per quel momento specifico. Se il timer ha solo il supporto a triangolo, allora questo è facilmente calcolata ma aggiunge ulteriori errore dal momento che la si potrebbe facilmente essere dato il via alla CPU tra il tempo di calcolare il vostro delta e il tempo che il timer viene inserito nel kernel.

Come già sottolineato, Windows non è un vero e proprio sistema operativo tempo. Quindi è necessario supporre che, anche se si pianifica un timer per scesi a ": 0010", il codice potrebbe anche non eseguire fino a ben dopo che il tempo (ad esempio, ": 0540"). Finché gestire correttamente questi problemi, le cose saranno "ok".

20ms è pari a circa la lunghezza di un intervallo di tempo su Windows. Non c'è modo di colpire 1ms tipo di temporizzazioni a finestre in modo affidabile senza una sorta di RT add on come Intime. In Windows corretta Credo che le opzioni sono WaitForSingleObject, SleepEx, e un ciclo occupato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top