2017-02-20 10 views
0

Je vais avoir le code ci-dessous pour afficher l'heure actuelle:Obtenez heure à l'heure changement

static void Main(string[] args) 
{ 
    while (true) 
    { 
     ShowDate(GetTime(),GetDate()); 
     //Here's my issue: 
     System.Threading.Thread.Sleep(1000); 
    } 
} 

//Clear Console and write current Date again. 
static void ShowDate(String time, String date) 
{ 
    Console.Clear(); 
    Console.WriteLine(date); 
    Console.WriteLine(time); 
} 
static string GetTime() 
{ 
    string timeNow = DateTime.Now.ToString("HH:mm:ss"); 
    return timeNow; 
} 
static string GetDate() 
{ 
    string dateNow = DateTime.Now.ToString("dd.MM.yy"); 
    return dateNow; 
} 

Eh bien, dans ma compréhension, Thread.Sleep(1000) montre que le temps chaque seconde mesuré après le début du programme. Donc, il ne montre pas l'heure parfaitement correcte. Je pourrais essayer une valeur inférieure pour Thread.Sleep(), mais c'est encore un peu inexact et devient probablement un peu inefficace. Est-il possible, par exemple, de mettre à jour l'heure chaque fois que le système met à jour son heure? Quelque chose comme un event listener peut-être?

+3

comment voulez-vous dire son «un peu inexact? –

+1

Qu'est-ce que vous devez accomplir? – NicoRiff

+0

Ce que vous essayez d'obtenir n'est pas clair. Voulez-vous simplement afficher le datetime actuel par intervalles d'une seconde? –

Répondre

1

Comme vous l'avez écrit, ce serait rafraîchir (écriture) temps chaque seconde - 0, 1, 2, 3 .. mais si le programme commencerait dans quelque temps intermédiaire, il irait comme 1,3, 2,3, 3,3

Ce n'est pas toujours le comportement attendu, mais un Event pour chaque changement de temps, serait également consommer - Vous pourriez peut-être savoir qu'il existe un certain "temps système", qui est compté dans le Ticks.

Cochez chaque processeur jumps à l'instruction suivante et comme il a quelques frequency, il peut recalculer l'heure actuelle à partir de celui-ci.

Cependant, .NET vous permet d'utiliser une préconfiguration Timers, qui peut être exécutée avec une précision de miliseconde.

code Exemple as in here:

using System; 
using System.Threading; 

public static class Program 
{ 
    public static void Main() 
    { 
     // Create a Timer object that knows to call our TimerCallback 
     // method once every 2000 milliseconds. 
     Timer t = new Timer(TimerCallback, null, 0, 2000); 
     // Wait for the user to hit <Enter> 
     Console.ReadLine(); 
    } 

    private static void TimerCallback(Object o) 
    { 
     // Display the date/time when this method got called. 
     Console.WriteLine("In TimerCallback: " + DateTime.Now); 
     // Force a garbage collection to occur for this demo. 
     GC.Collect(); 
    } 
} 

Important: Vous utilisez Thread.Sleep(), ce qui entraînera Thread à Stopp tous ses travaux, c'est une façon vraiment insuffisante de retarder une activité et doit être utilisé au minimum. Il y a des occasions spéciales, où c'est vraiment utilisable, mais ce n'est sûrement pas le cas.

1

Au lieu d'utiliser un Thread.Sleep pour arrêter l'exécution de cette discussion, je pense être mieux vous en aurez une minuterie classique utilise:

static void Main(string[] args) 
{ 
    System.Timers.Timer timer = new System.Timers.Timer(1000); 
    timer.Elapsed += Tim_Elapsed; 
    timer.Start(); 
} 

private void Tim_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    ShowDate(); 
} 
+0

Eh bien, merci. Le minuteur est plus précis non? Et n'interrompt pas le fil actuel? –

+0

System.Timers.Timer (ne pas confondre avec d'autres classes Timer) est exécuté sur le pool de threads du système, il ne bloquera donc pas votre thread principal. Il se déclenche toujours dans le temps écoulé que vous avez déclaré, à partir de l'heure spécifique à laquelle la méthode Start() est appelée. Exemple: si vous démarrez la méthode à 22: 31: 15.332, il sera exécuté à 22: 31: 16.332, pas à 22: 31: 16.000 – NicoRiff

3

Je l'approche avec une classe d'horloge personnalisée qui émet des événements toutes les secondes. En mesurant le temps restant avant la prochaine seconde, nous pouvons attendre jusqu'à ce moment, puis déclencher un événement.

Tirer parti async/await pour l'avantage qu'il apporte la clarté du code et IDisposable pour le nettoyage, cela pourrait ressembler à ceci:

void Main() 
{ 
    using(var clock = new Clock()) 
    { 
     clock.Tick += dt => Console.WriteLine(dt); 
     Thread.Sleep(20000); 

    } 

} 
//sealed so we don't need to bother with full IDisposable pattern 
public sealed class Clock:IDisposable 
{ 
    public event Action<DateTime> Tick; 
    private CancellationTokenSource tokenSource; 
    public Clock() 
    { 
     tokenSource = new CancellationTokenSource(); 
     Loop(); 
    } 
    private async void Loop() 
    { 
     while(!tokenSource.IsCancellationRequested) 
     { 
      var now = DateTime.UtcNow; 
      var nowMs = now.Millisecond; 
      var timeToNextSecInMs = 1000 - nowMs; 
      try 
      { 
       await Task.Delay(timeToNextSecInMs, tokenSource.Token); 

      } 
      catch(TaskCanceledException) 
      { 
       break; 
      } 
      var tick = Tick; 
      if(tick != null) 
      { 
       tick(DateTime.UtcNow); 
      } 
     } 

    } 
    public void Dispose() 
    { 
     tokenSource.Cancel(); 
    } 
} 
+0

J'aime cette réponse car un système similaire est utilisé dans les jeux pour rafraîchir dans un cadre particulier taux. – Tatranskymedved