Question

J'ai une machine qui utilise un client NTP pour synchroniser l'heure d'Internet il est donc horloge du système devrait être assez précis.

J'ai une demande que je suis en développement qui enregistre des données en temps réel, les processus, puis le transmet. Ce que je voudrais faire est maintenant sortie que les données toutes les millisecondes N alignées avec l'horloge du système. Ainsi, par exemple si je voulais faire des intervalles de 20ms, mes oututs devrait être quelque chose comme ceci:

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

J'ai vu des suggestions pour l'utilisation de la classe chronomètre, mais que des mesures que le temps s'étend, par opposition à la recherche d'horodatage spécifiques. Le code pour le faire est en cours d'exécution dans son propre thread, ce qui devrait être un problème si je dois faire des appels relativement blocage.

Toutes les suggestions sur la façon d'y parvenir à un raisonnable (proche ou mieux que 1ms précision serait bien) serait très chaleureusement reçu.

Était-ce utile?

La solution

Je ne sais pas comment il joue avec C ++ / CLR, mais vous voulez probablement regarder minuteries multimédia ,
Windows est pas vraiment en temps réel mais est aussi proche qu'il obtient

Autres conseils

Vous pouvez obtenir un horodatage assez précis sur timeGetTime () lorsque vous réduisez la période. Vous aurez juste besoin d'un peu de travail pour obtenir sa valeur de retour converti en un temps d'horloge. Cet exemple de code C # montre l'approche:

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

À la réflexion, c'est juste mesure. Pour obtenir une action effectuée périodiquement, vous devrez utiliser timeSetEvent (). Tant que vous utilisez timeBeginPeriod (), vous pouvez obtenir la période de rappel assez proche de 1 msec. Un nicety est qu'il compense automatiquement lorsque le rappel précédent était en retard pour une raison quelconque.

Votre meilleur pari utilise l'assembleur en ligne et en écrivant ce morceau de code en tant que pilote de périphérique.

De cette façon:

  • Vous avez le contrôle sur le nombre instruction
  • Votre demande aura la priorité d'exécution

vous pouvez finalement pas garantir ce que vous voulez parce que le système d'exploitation doit honorer les demandes d'autres processus à exécuter, ce qui signifie que quelque chose d'autre peut toujours être occupé exactement au moment où vous voulez que votre processus soit en cours d'exécution. Mais vous pouvez améliorer les choses à l'aide timeBeginPeriod pour le rendre plus probable que votre processus peut être commuté en temps opportun, et étant peut-être la ruse avec la façon dont vous attendez entre les itérations - par exemple. dormir pour la plupart, mais pas tout le temps, puis en utilisant une boucle chargée pour le reste.

Essayez de faire cela dans deux threads. Dans un fil, utilisez quelque chose comme cette pour interroger une minuterie de haute précision dans une boucle. Lorsque vous détectez un horodatage qui aligne (ou est raisonnablement proche) une limite 20ms, envoyer un signal à votre fil de sortie du journal ainsi que l'horodatage à utiliser. Votre fil de sortie du journal serait tout simplement attendre un signal, puis saisissez l'horodatage et la sortie passée dans tout ce qui est nécessaire. Garder les deux dans des threads séparés fera en sorte que votre fil de sortie du journal ne gêne pas la minuterie (ce qui est essentiellement émule une interruption de l'horloge matérielle, ce qui serait la façon dont je le ferais sur une plate-forme embarquée).

CreateWaitableTimer / SetWaitableTimer et un fil de haute priorité doit être précise à environ 1ms. Je ne sais pas pourquoi le champ milliseconde dans votre exemple de sortie a quatre chiffres, la valeur maximale est de 999 (depuis 1000 ms = 1 seconde).

Depuis que vous avez dit, cela ne doit pas être parfait, il y a quelque chose qui peut être fait.

Pour autant que je sache, il n'existe pas une minuterie qui permet de synchroniser avec un temps spécifique. Donc, vous devrez calculer votre prochaine fois et programmer la minuterie pour ce moment précis. Si votre minuterie ne prend en charge delta, puis qui est facilement calculée, mais ajoute plus d'erreur puisque l'on pouvait facilement être lancé la CPU entre le moment où vous calculez votre delta et le temps de la minuterie est entré dans le noyau.

Comme nous l'avons souligné, Windows n'est pas un système d'exploitation en temps réel. Vous devez donc supposer que, même si vous planifiez une minuterie pour l'arrêt obtenu « : 0010 », votre code pourrait ne pas exécuter même bien après que le temps (par exemple, « : 0540 »). Tant que vous gérez correctement ces questions, les choses seront « ok ».

20ms est à peu près la longueur d'une tranche de temps sur Windows. Il n'y a pas moyen de frapper 1ms sorte de timings dans les fenêtres de manière fiable sans une sorte de RT ajouter sur comme INTIME. Dans les fenêtres bon je pense que vos options sont WaitForSingleObject, SleepEx, et une boucle chargée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top