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 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
-
1Even 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 Answers
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...

- 3,115
- 2
- 36
- 56
You can use some schedule libraries, like Quartz.net, it provides examples and easy to use: http://quartznet.sourceforge.net/

- 1,102
- 1
- 8
- 17
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.

- 52,015
- 16
- 101
- 139