开发者

C# timer synchronized with Datetime.Now

In C# how to create a timer that synchronize with tick of system DateTime. 开发者_如何学编程custom timer should tick whenever the seconds change for DateTime.Now


You will find if you check some of the previous questions on SO, you are going to have a very hard time getting accuracy with your timer. Here is a small sample of previous questions:

  • Timer takes 10 ms more than interval
  • C# Why are timer frequencies extremely off?
  • .NET, event every minute (on the minute). Is a timer the best option?

Here is another previous question which may provide you some help.


What would be your desired precision ?

If you say that 1ms is precise enough (or 10, or 100), you could always do a loop which compares the current time and one saved from the previous iteration, and start a thread when the seconds value of the current time value changes...


You can use some schedule libraries, like Quartz.net, it provides examples and easy to use: http://quartznet.sourceforge.net/


This code uses a System.Threading.Timer. It will look at the millisecond-offset the trigger is called. If the error is outside the accepted range, it will re-adjust the timer and it will correct the interval by averaging the error per tick.

class Program {
    const int MAX_ERROR_IN_MILLISECONDS = 20;
    const int ONE_SECOND = 1000;
    const int HALF_SECOND = ONE_SECOND / 2;

    private static System.Threading.Timer timer;

    static void Main(string[] args) {

        timer = new System.Threading.Timer(Tick);

        timer.Change(ONE_SECOND - DateTime.Now.Millisecond, ONE_SECOND);
        Console.ReadLine();
    }

    private static int ticksSynced = 0;
    private static int currInterval = ONE_SECOND;
    private static void Tick(object s) {
        var ms = DateTime.UtcNow.Millisecond;
        var diff = ms > HALF_SECOND ? ms - ONE_SECOND : ms;
        if (Math.Abs(diff) < MAX_ERROR_IN_MILLISECONDS) {
            // still synced
            ticksSynced++;
        } else {
            // Calculate new interval
            currInterval -= diff / ticksSynced;
            timer.Change(ONE_SECOND - ms, currInterval);
            Console.WriteLine("New interval: {0}; diff: {1}; ticks: {2}", currInterval, diff, ticksSynced);
            ticksSynced = 0;
        }
        Console.WriteLine(ms);
    }
}

As you can see, you cannot trigger exactly on the second change in Windows. You can try to get close.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜