12
votes

C # La minuterie se fait tirer avant leur période d'intervalle

Nous obtenons le problème suivant tout en utilisant System.threading.Timer (.NET 2.0) à partir d'un service Windows.

  1. Il y a environ 12 objets de minuterie différents ..
  2. Chaque minuterie a duré le temps et l'intervalle. Ceci est réglé correctement.
  3. On observe qu'après 3 à 4 heures, les minuteries commencent à signaler avant leur intervalle. Par exemple, si la minuterie est censée signaler à 4:59:59, il est signalé à 4:59:52, 7 secondes plus tôt.

    Quelqu'un peut-il me dire quelle est la cause de ce comportement et quelle est la solution pour cela?

    merci, Swati


0 commentaires

4 Réponses :


0
votes

Peut-être que la ré-planification est effectuée après une opération qui prend quelques secondes à compléter. Ou ne contrôlez-vous pas cela?


0 commentaires

0
votes

Ceci ne peut pas être le contrôle car il dépend de la vitesse du système, si vous avez une super donnée, il peut y avoir suffisamment de différence, mais si vous avez un PC normal, il y aura une différence dans l'intervalle de minuterie après une exécution longue. .

espère que cela aidera.


0 commentaires

10
votes

Grande question ... et voici la raison:

"timing" est une chose délicate lorsqu'il s'agit d'ordinateurs ... Vous pouvez jamais em> s'appuyer sur un "intervalle" pour être parfait . Certains ordinateurs «cocheront» la minuterie que tous les 14 à 15 millisecondes, d'autres plus fréquemment que cela, certains moins fréquemment. P>

donc: p> xxx pre>

pourrait Prenez partout de 1 à 30 millisecondes à exécuter. P>

Au lieu de cela, si vous avez besoin d'une minuterie plus précise - vous devez capturer la dateTime du moment où vous commencerez, puis dans vos minuteries, vous devriez vérifier en soustrayant DateTime.now et votre heure originale pour voir si c'est "Time d'exécuter" votre code. P>

Voici quelques échantillons de code de ce que vous devez faire: P>

if (DateTime.Now.Subtract(startDate).TotalSeconds % 3 == 0)
{
    // This code will fire every 3 seconds.
}


2 commentaires

Je sais que ce n'est qu'un exemple, mais n'auriez-vous pas augmenter l'intervalle de minuterie à quelque chose comme 100 ou même 500 ms? Je sais que vous pourriez perdre un peu de précision, mais cela ne serait-il pas meilleur que d'avoir un feu de minuterie 1000 fois une seconde lorsque vous n'avez besoin que de résultats toutes les 3 secondes?


Ouais, 1000 interrompt chaque seconde est un peu beaucoup.



8
votes

L'explication de Timothy est convaincante, mais System.threading.Timer fonctionne déjà de cette façon. Au moins dans la mise en oeuvre du rotor, il utilise la valeur renvoyée par GettickCount () pour calculer lorsque le prochain rappel est due. Il n'est pas terriblement probable que le vrai CLR le fait aussi, il est plus susceptible d'utiliser CreateTimerQuerQueTimer (). Néanmoins, cette fonction API devrait également dépendre de la coche interne incrémentée par l'interruption de la tique de l'horloge.

en cause se trouve la coche de l'horloge interne (comme retournée par gettickcount () et de l'environnement.TickCount) est synchronisée avec le temps de mur absolu (comme retourné par DateTime.now). Malheureusement, c'est un détail de mise en œuvre de la HAL sur votre machine, la couche d'abstraction matérielle. Le constructeur de la machine peut fournir une HAL personnalisée, une modifie pour travailler avec le bios et le chipset de la machine.

J'attendrais des problèmes si la machine dispose de deux sources de synchronisation, une puce d'horloge conçue pour suivre le temps de mur et conserve que vous débranchez la machine, et une autre fréquence disponible sur le chipset pouvant être divisé pour fournir l'interruption de l'horloge. L'IBM original sur PC a fonctionné de cette façon. La puce d'horloge peut généralement être approuvée, l'horloge serait grossièrement si ce n'est pas précis. Le chipset ne peut pas, couper les angles sur la qualité des oscillateurs est un moyen facile d'économiser un sou.

Résolvez votre problème en évitant de longues périodes sur votre minuterie et en recalculant la prochaine heure du temps de DateTime.Now dans le rappel.


1 commentaires

Merci de votre aide. La ré-calcul des minuteries peut résoudre mon problème. Je vais essayer ça. Encore merci !!