inaccurate .NET timer?

2019-02-26 21:25发布

I'm developing an application and I need to get the current date from a server (it differs from the machine's date). I receive the date from the server and with a simple Split I create a new DateTime:

globalVars.fec = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(infoHour[0]), int.Parse(infoHour[1]), int.Parse(infoHour[2]));

globalVars is a class and fec is a public static variable so that I can access it anywhere in the application (bad coding I know...). Now I need to have a timer checking if that date is equal to some dates I have stored in a List and if it is equal I just call a function.

List<DateTime> fechas = new List<DateTime>();

Before having to obtain the date from a server I was using computer's date, so to check if the dates matched I was using this:

private void timerDatesMatch_Tick(object sender, EventArgs e)
{
    DateTime tick = DateTime.Now;
    foreach (DateTime dt in fechas)
    {
        if (dt == tick)
        {
            //blahblah
        }
    }
}

Now I have the date from the server so DateTime.Now can't be used here. Instead I have created a new timer with Interval=1000 and on tick I'm adding 1 second to globalVars.fec using:

globalVars.fec = globalVars.fec.AddSeconds(1);

But the clock isn't accurate and every 30 mins the clock loses about 30 seconds.

Is there another way of doing what I'm trying to do? I've thought about using threading.timer instead but I need to have access to other threads and non-static functions.

标签: c# .net timer
3条回答
祖国的老花朵
2楼-- · 2019-02-26 21:48

Here is a reliable 1 μs Timer

See https://stackoverflow.com/questions/15725711/obtaining-microsecond-precision-using-net-without-platform-invoke?noredirect=1#comment22341931_15725711

I guarantee its faster and more accurate then StopWatch and PerformanceCounters and uses the fractions of a second you have in the time slice wisely!

查看更多
老娘就宠你
3楼-- · 2019-02-26 21:56

If you create atimer with an interval of 1000ms, it will be called no sooner than 1000ms. So you can pretty much guarantee that it will be called in more than 1000ms, which means you will "lose" time by adding 1s on this timer tick - This will accumulate error with every tick. A better approach is to record a start time and use the current time to determine the current offset from that known start time, so that you don't accumulate any error in your time keeping. (There will still be some error, but you will not drift out of touch with real-time over time)

Different timers (Forms.Timer, Thread.Timer etc) will give different accuracies as well - Forms.Timer is particularly poor for accuracy.

You could also use a high performance time to keep track of the time better - see here, for example.

查看更多
Bombasti
4楼-- · 2019-02-26 21:59

Store the difference between the server's time and local time. Calculate the servers' time when you need it using that difference.

查看更多
登录 后发表回答