2

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

Tintu Mon
  • 81
  • 1
  • 5
  • You need to be triggered once per second, or within a certain range when the second has changed? What's the purpose? – GvS Jun 08 '10 at 09:55
  • I want to get triggered whenever the DateTime.Now.Second changes. If I start a timer with a timespan of 1 second,it won't be firing exactly when the system time changes. – Tintu Mon Jun 08 '10 at 10:06
  • You could do this with a busy wait loop, but hopefully there is a better way. – Mikael Svenson Jun 08 '10 at 10:15
  • 1
    Even if you attempt something like a callback function, it won't be called exactly at the second tick. Try to sleep something like 10 ms short of your target, that should improve your accuracy to within a few ms. Increasing priority may also help to improve accuracy. – apoorv020 Jun 08 '10 at 10:26

4 Answers4

4

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:

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

Community
  • 1
  • 1
slugster
  • 49,403
  • 14
  • 95
  • 145
0

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...

Shimrod
  • 3,115
  • 2
  • 36
  • 56
0

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

Andrew
  • 1,102
  • 1
  • 8
  • 17
0

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.

GvS
  • 52,015
  • 16
  • 101
  • 139