获取当前时间的时间变化

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