获取当前时间的时间变化
Get current time on time change
我有以下代码来显示当前时间:
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
之类的东西?
与其使用 Thread.Sleep 来停止线程执行,我认为你最好使用传统的计时器:
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、1、2、3 ..
但是如果程序在某个中间时间开始,它会像 1.3, 2.3, 3.3
这并不总是预期的行为,但每次更改的 Event
也会消耗大量资源 - 您可能知道存在一些 "system time",这被计入 Ticks
.
每次处理器 jumps
到下一条指令时都会发生滴答,因为它有一些 frequency
,它可以 re-calculate 当前时间。
但是 .NET
允许您使用一些 pre-build 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.Sleep()
,这将导致Thread
停止所有工作,这确实是延迟某些activity 并且应该尽量少用。有一些特殊的场合,确实有用,但肯定不是这个。
我会使用每秒发出事件的自定义时钟 class 来解决这个问题。通过测量下一秒到期之前的剩余时间,我们可以等到那一刻,然后触发一个事件。
利用 async/await
带来代码清晰度的好处,利用 IDisposable
带来 clean-up,这可能看起来像这样:
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();
}
}
我有以下代码来显示当前时间:
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
之类的东西?
与其使用 Thread.Sleep 来停止线程执行,我认为你最好使用传统的计时器:
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、1、2、3 .. 但是如果程序在某个中间时间开始,它会像 1.3, 2.3, 3.3
这并不总是预期的行为,但每次更改的 Event
也会消耗大量资源 - 您可能知道存在一些 "system time",这被计入 Ticks
.
每次处理器 jumps
到下一条指令时都会发生滴答,因为它有一些 frequency
,它可以 re-calculate 当前时间。
但是 .NET
允许您使用一些 pre-build 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.Sleep()
,这将导致Thread
停止所有工作,这确实是延迟某些activity 并且应该尽量少用。有一些特殊的场合,确实有用,但肯定不是这个。
我会使用每秒发出事件的自定义时钟 class 来解决这个问题。通过测量下一秒到期之前的剩余时间,我们可以等到那一刻,然后触发一个事件。
利用 async/await
带来代码清晰度的好处,利用 IDisposable
带来 clean-up,这可能看起来像这样:
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();
}
}