2010-06-08 5 views
2

En C#, comment créer un minuteur synchronisé avec tick du système DateTime. La minuterie personnalisée doit cocher chaque fois que les secondes changent pour DateTime.NowMinuteur C# synchronisé avec Datetime.Now

+0

Vous devez être déclenché une fois par seconde, ou dans une certaine plage lorsque la seconde a changé? Quel est le but? – GvS

+0

Je veux être déclenché chaque fois que DateTime.Now.Second change. Si je démarre une minuterie avec une durée de 1 seconde, elle ne se déclenchera pas exactement lorsque l'heure du système changera. –

+0

Vous pouvez le faire avec une boucle d'attente occupée, mais j'espère qu'il y a une meilleure façon. –

Répondre

0

Quelle serait la précision désirée? Si vous dites que 1ms est assez précis (ou 10, ou 100), vous pouvez toujours faire une boucle qui compare l'heure actuelle et une enregistrée de l'itération précédente, et démarrer un thread lorsque la valeur des secondes du courant valeur temps ...

0

Ce code utilise un System.Threading.Timer. Il regardera le milliseconde-décalage que le déclencheur est appelé. Si l'erreur est en dehors de la plage acceptée, elle réajustera la minuterie et corrigera l'intervalle en faisant la moyenne de l'erreur par tick.

class Program { 
    const int MAX_ERROR_IN_MILLISECONDS = 20; 
    const int ONE_SECOND = 1000; 
    const int HALF_SECOND = ONE_SECOND/2; 

    private static System.Threading.Timer timer; 

    static void Main(string[] args) { 

     timer = new System.Threading.Timer(Tick); 

     timer.Change(ONE_SECOND - DateTime.Now.Millisecond, ONE_SECOND); 
     Console.ReadLine(); 
    } 

    private static int ticksSynced = 0; 
    private static int currInterval = ONE_SECOND; 
    private static void Tick(object s) { 
     var ms = DateTime.UtcNow.Millisecond; 
     var diff = ms > HALF_SECOND ? ms - ONE_SECOND : ms; 
     if (Math.Abs(diff) < MAX_ERROR_IN_MILLISECONDS) { 
      // still synced 
      ticksSynced++; 
     } else { 
      // Calculate new interval 
      currInterval -= diff/ticksSynced; 
      timer.Change(ONE_SECOND - ms, currInterval); 
      Console.WriteLine("New interval: {0}; diff: {1}; ticks: {2}", currInterval, diff, ticksSynced); 
      ticksSynced = 0; 
     } 
     Console.WriteLine(ms); 
    } 
} 

Comme vous pouvez le voir, vous ne pouvez pas déclencher exactement sur le deuxième changement dans Windows. Vous pouvez essayer de vous rapprocher.