2017-02-20 23 views
0

に現在の時刻を取得します。私は、現在の時刻を表示するために、次のコードを持っている:時間変化

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

まあ、私の理解では、Thread.Sleep(1000)は唯一、すべてが第二のプログラムの開始後に測定した時間を示しています。それで、完全に正しい時刻は示されません。私はThread.Sleep()の値を低くしてみることもできますが、それはまだまだ不正確で、おそらく非効率的なものになります。 たとえば、システム自体が時間を更新するたびに時間を更新する方法はありますか?おそらくevent listenerのようなものでしょうか?

+3

どのようにあなたがその「ちょっと不正確な」を意味しています:それは、コードの明瞭さとクリーンアップのためIDisposableにもたらす利益のためにasync/awaitを活用

、これは次のようになりますか? –

+1

あなたは何を達成する必要がありますか? – NicoRiff

+0

あなたが達成しようとしていることは明確ではありません。現在の日時を1秒間隔で表示したいだけですか? –

答えて

1

を、これは(書き込み)時間を秒ごとに更新します - 0、1、2、3 ... しかし、プログラムは、いくつかの中間の時間に起動するならば、それは1.3、2.3、3.3

のように行くだろうこれは、常に予想される動作ではなく、それぞれの時間変化についてEventまた、あなたはおそらく、いくつかの "システム時間"が存在し、Ticksでカウントされていることを知っているかもしれません。

tickはプロセッサjumpsが次の命令になるたびに発生し、frequencyがあるため、現在の時刻を再計算することができます。

ただし、.NETでは、事前ビルドTimersを使用することができます。これは、ミリ秒の前提で実行できます。

例コード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(); 
    } 
} 

重要:あなたはThreadは、そのすべての作業をSTOPPするようになりますThread.Sleep()を、使用している、これは実際にいくつかの活動を遅らせる不充分な方法で、最小限に使用する必要があります。それは本当に有用ないくつかの特殊なocasionsがありますが、これは確かに一つではありません。

1

代わりにスレッドの実行を停止するのThread.sleepを使用しての、私はyou'llは、従来のタイマー使用して良いことだと思う:あなたが書いたとおり

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

まあ、ありがとう。タイマーはより正確ですよね?そして、現在のスレッドを中断しない? –

+0

System.Timers.Timer(他のTimerクラスと混同しないでください)は、システムスレッドプールで実行されるため、メインスレッドをブロックしません。 Start()メソッドが呼び出された特定の時間から、宣言した経過時間に常に起動します。例:22:31:15.332でメソッドを開始した場合、22:31:16.332ではなく22:31:16.332で再度実行されます。 – NicoRiff

3

毎秒イベントを発行するカスタムクロッククラスを使用してこれにアプローチします。次の秒が経過する前の残りの時間を測定することで、その瞬間まで待ってからイベントを発生させることができます。

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

このようなシステムがゲームで特定のフレーム単位でリフレッシュするために使用されるので、レート。 – Tatranskymedved