我有以下代码来显示当前时间:
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
这样的东西?
答案 0 :(得分:3)
我使用每秒发送事件的自定义时钟类来解决这个问题。通过测量下一秒之前的剩余时间,我们可以等到那一刻,然后发射一个事件。
利用async/await
带来的代码清晰度和IDisposable
清理带来的好处,可能看起来像这样:
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();
}
}
答案 1 :(得分:1)
不使用Thread.Sleep来停止执行Thread,我认为使用传统的Timer会更好:
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();
}
答案 2 :(得分:1)
正如您所写,这将每秒刷新(写入)时间 - 0,1,2,3 .. 但是如果程序会在中间时间开始,那就像1.3,2.3,3.3
这并不总是预期的行为,但每次更改时Event
也会消耗 - 您可能知道存在一些“系统时间”,这会计入Ticks
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.Sleep()
,这将导致Thread
停止其所有工作,这实际上是延迟某些活动的低效方式,应该最低限度地使用。有一些特殊的场合,它确实可用,但肯定不是那个。