Frage

Ich habe eine Maschine, die ein NTP-Client verwendet, um Internet-Zeit zu synchronisieren, so dass es die Systemuhr ziemlich genau sein soll.

Ich habe einen Antrag bekommen, die ich entwickle, die Daten in Echtzeit protokolliert, verarbeitet sie und leitet sie dann an. Was möchte ich jetzt tun ist, ausgegeben, dass die Daten alle N Millisekunden mit dem Systemtakt ausgerichtet sind. So zum Beispiel, wenn ich Intervalle von 20 ms tun wollte, mein oututs soll so etwas sein:

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

Ich habe Vorschläge gesehen die Stoppuhr-Klasse für die Verwendung, sondern dass nur Maßnahmen Zeiträume als für bestimmte Zeitmarken zu suchen entgegen. Der Code, dies zu tun ist in einem eigenen Thread ausgeführt wird, so sollte ein Problem sein, wenn ich ein paar relativ blockieren Anrufe muß tun.

Alle Vorschläge, wie dies zu einem vernünftigen erreichen sehr dankbar würden erhalten (in der Nähe oder sogar besser als 1ms Präzision wäre schön).

War es hilfreich?

Lösung

Sie wissen nicht, wie gut sie spielt mit C ++ / CLR, aber Sie wollen wahrscheinlich unter Multimedia-Timer ,
Windows ist nicht wirklich in Echtzeit, aber das ist so nah wie es

bekommt

Andere Tipps

Sie können ein ziemlich genauen Zeitstempel aus timeGetTime () erhalten, wenn Sie die Zeitdauer reduzieren. Sie müssen nur etwas Arbeit benötigen ihren Rückgabewert auf eine Taktzeit umgewandelt zu bekommen. Diese Probe C # -Code zeigt der Ansatz:

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

Am zweiten Gedanken, das ist nur Messung. Um eine Aktion zu erhalten in regelmäßigen Abständen durchgeführt, Sie verwenden müssen TimeSetEvent (). Solange Sie timebeginperiod () verwenden, können Sie die Rückrufperiode ziemlich nahe an 1 ms erhalten. Ein nicety ist, dass es automatisch kompensieren, wenn der vorherige Rückruf spät aus irgendeinem Grunde war.

Ihre beste Wette ist, mit Inline-Assembler und Schreiben dieses Stück Code als Gerätetreiber.

Auf diese Weise:

  • Sie haben die Kontrolle über Anweisung count
  • Ihre Anwendung wird die Ausführung Priorität

Schließlich kann man nicht garantieren, was Sie wollen, weil das Betriebssystem zu Ehren Anfragen von anderen Prozessen zu laufen hat, was bedeutet, dass etwas anderes immer beschäftigt sein kann, genau im Moment, dass Sie Ihren Prozess wollen laufen. Aber man kann die Situation verbessern timeBeginPeriod Verwendung zu machen wahrscheinlicher, dass Ihr Prozess kann in einer angemessenen Art und Weise umgeschaltet werden, und vielleicht schlau zu sein mit, wie Sie Iterationen warten zwischen - zB. Schlafen für die meisten, aber nicht die ganze Zeit und dann für den Rest einer Besetzt-Schleife.

Versuchen Sie, diese Themen in zwei tun. In einem Thread, die Verwendung so etwas wie dieser einen hochgenaue Zeitgeber in einer Schleife abzufragen. Wenn Sie einen Zeitstempel, dass ausrichtet (oder ist ziemlich nahe an) ein 20 ms Grenze erkennen, zusammen mit dem Zeitstempel verwenden, um ein Signal an dem Log-Ausgabe-Thread zu senden. Ihr Log-Ausgabe-Thread würde einfach auf ein Signal warten, dann wird der Zeitstempel und die Ausgabe in gebenen greifen, was auch immer nötig ist. Halten Sie die beide in getrennten Threads werden sicherstellen, dass Ihr Log-Ausgabe-Thread nicht stört mit dem Timer (dies im Wesentlichen ein Hardware-Timer-Interrupt emuliert, die die Art und Weise sein, würde ich es auf einer Embedded-Plattform tun würde).

Create / SetWaitableTimer und ein hoher Priorität Thread sollte auf etwa 1 ms genau. Ich weiß nicht, warum das Millisekundenfeld in Ihrem Beispiel Ausgabe vier Ziffern hat, der Maximalwert beträgt 999 (seit 1000 ms = 1 Sekunde).

Da, wie Sie gesagt haben, diese nicht perfekt sein muss, gibt es etwas, was getan werden kann.

Soweit ich weiß, gibt existiert nicht einen Timer, dass Synchronisierungen mit einem bestimmten Zeitpunkt. So werden Sie Ihr nächstes Mal berechnen müssen und planen Sie den Timer für diese bestimmte Zeit. Wenn nur die Timer-Delta-Unterstützung hat, dann ist das einfach berechnet wird, aber mehr Fehler fügt hinzu, da die Sie leicht von der CPU zwischen der Zeit getreten werden könnten berechnen Sie Ihr Delta und die Zeit der Timer in den Kernel eingegeben wird.

Wie bereits erwähnt, ist die Windows nicht ein Echtzeit-Betriebssystem. So Sie, dass selbst übernehmen müssen, wenn Sie einen Timer planen, um ausstieg bei „: 0010“ dem Code, führt vielleicht nicht einmal bis weit nach der Zeit (zum Beispiel „: 0540“). Solange Sie diese Fragen richtig handhaben, werden die Dinge sein „ok“.

20 ms ist etwa die Länge einer Zeitscheibe unter Windows. Es gibt keine Möglichkeit 1ms Art von Timings in den Fenstern zu treffen zuverlässig ohne irgendeine Art von RT add on wie Intime. In Windows richtigen denke ich Ihre Optionen sind WaitForSingleObject, SleepEx und eine geschäftige Schleife.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top