C# 按时间更改获取当前时间

C# 按时间更改获取当前时间,c#,multithreading,timer,clock,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

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

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()
设置一个较低的值,但这仍然有点不准确,可能会变得有点低效。
例如,是否有任何可能的方法可以在系统每次更新其时间时更新时间?类似于
事件监听器的东西
可能吗

不要使用线程。睡眠停止线程执行,我认为最好使用常规计时器:

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

与使用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那样运行

这并非总是预期的行为,但每次时间更改都会发生
事件
,这也会消耗时间-您可能知道存在一些“系统时间”,这些时间在
刻度中计算

每次处理器
跳转到下一条指令时都会出现勾号,由于它有一些
频率,因此可以从中重新计算当前时间

但是,
.NET
允许您使用一些预构建的
计时器
,可以以毫秒的精度运行

示例代码:

使用系统;
使用系统线程;
公共静态类程序
{
公共静态void Main()
{
//创建一个知道调用TimerCallback的Timer对象
//方法每2000毫秒一次。
计时器t=新计时器(TimerCallback,null,0,2000);
//等待用户点击
Console.ReadLine();
}
专用静态void TimerCallback(对象o)
{
//显示调用此方法的日期/时间。
WriteLine(“In-TimerCallback:+DateTime.Now”);
//强制对此演示执行垃圾回收。
GC.Collect();
}
}

重要提示:您正在使用
Thread.Sleep()
,这将导致
线程停止其所有工作,这确实不是延迟某些活动的有效方法,应该尽量少用。有一些特殊的地方,它确实有用,但这肯定不是唯一的地方。

如您所写,这将每秒刷新(写入)一次-0、1、2、3。。 但是,如果该程序在某个中间时间启动,它将像1.3、2.3、3.3那样运行

这并非总是预期的行为,但每次时间更改都会发生
事件
,这也会消耗时间-您可能知道存在一些“系统时间”,这些时间在
刻度中计算

每次处理器
跳转到下一条指令时都会出现勾号,由于它有一些
频率,因此可以从中重新计算当前时间

但是,
.NET
允许您使用一些预构建的
计时器
,可以以毫秒的精度运行

示例代码:

使用系统;
使用系统线程;
公共静态类程序
{
公共静态void Main()
{
//创建一个知道调用TimerCallback的Timer对象
//方法每2000毫秒一次。
计时器t=新计时器(TimerCallback,null,0,2000);
//等待用户点击
Console.ReadLine();
}
专用静态void TimerCallback(对象o)
{
//显示调用此方法的日期/时间。
WriteLine(“In-TimerCallback:+DateTime.Now”);
//强制对此演示执行垃圾回收。
GC.Collect();
}
}

重要提示:您正在使用
Thread.Sleep()
,这将导致
线程停止其所有工作,这确实不是延迟某些活动的有效方法,应该尽量少用。有一些特殊的ocation,在那里它确实是可用的,但这肯定不是唯一的一个。

我将使用每秒发出事件的自定义时钟类来实现这一点。通过测量下一秒即将过去之前的剩余时间,我们可以等到那一刻,然后触发事件

利用
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();
    }
}
void Main()
{
使用(var clock=new clock())
{
clock.Tick+=dt=>Console.WriteLine(dt);
睡眠(20000);
}
}
//密封,所以我们不需要麻烦与完整的IDisposable模式
公共密封类时钟:IDisposable
{
公共事件行动;
私有取消令牌源令牌源;
公钟
{
tokenSource=新的CancellationTokenSource();
Loop();
}
私有异步void循环()
{
而(!tokenSource.IsCancellationRequested)
{
var now=DateTime.UtcNow;
var nowMs=now.毫秒;
var timeToNextSecInMs=1000-nowMs;
尝试
{
wait Task.Delay(timeToNextSecInMs,tokenSource.Token);
}
捕获(TaskCanceledException)
{
打破
}
var tick=tick;
如果(勾选!=null)
{
勾选(DateTime.UtcNow);
}
}
}
公共空间处置()
{
tokenSource.Cancel();
}
}

我将使用每秒发出事件的自定义时钟类来实现这一点。通过测量下一秒即将过去之前的剩余时间,我们可以等到那一刻,然后触发事件

利用
async/await
带来代码清晰的好处,并利用
IDisposable
进行清理,这可能类似于