获取当前时间变化

时间:2017-02-20 12:37:34

标签: c# multithreading timer clock

我有以下代码来显示当前时间:

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 个答案:

答案 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停止其所有工作,这实际上是延迟某些活动的低效方式,应该最低限度地使用。有一些特殊的场合,它确实可用,但肯定不是那个。