I am trying to get a timer run every minute in sync with the system clock (00:01:00, 00:02:00, 00:03:00, etc). Will the following code produce a stable timer? I've tried running it. The timer does precisely run every min. But the question is will it start to wander off, say, after several months?
private System.Timers.Timer timer;
public frmMain()
{
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Interval = GetInterval();
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Do processing
timer.Interval = GetInterval();
timer.Start();
}
private double GetInterval()
{
DateTime now = DateTime.Now;
return ((60 - now.Second) * 1000 - now.Millisecond);
}
It won't.
DateTime.Now uses the system clock as the reference timer, so your timer will always stay in sync with it, modulus the few milliseconds of system clock resolution.
I don't see how it can wander off, everytime the timer ticks, it determines how long it is to the next exact minute and sets the interval accordingly. In theory it is actually quite ingenious, because I timer by itself would wander off. The only way to know for sure would be to test it of course, so as long as your UI doesn't freeze for more then 60 seconds, (maybe 50s to play it safe) there won't be a problem. Keep in mind that laptops will often go to sleep when left for a time, or the lid is closed, this will cause a glitch.
Depending on what you are attemping to do though, why not just use the system time, to send an event everytime the minute changes?
The big picture looks fine, GetInterval will always return a positive value, and so on. I only see a few caveats:
If standby/resume happens then you may have one run at a non-round time
If timer_Elapsed takes more than a minute to complete then you will miss a beat
If the system is so overloaded that timer_Elapsed is scheduled 40/50 seconds in delay AND timer_Elapsed takes more than 60 - delay seconds, you will miss a beat
Your code won't drift, but there will (inevitably) be jitter as Timer callbacks are rarely bang on the requested interval.
The only potential problem I can see with this code is if the ThreadPool were under such strain that your timer callback was not dequeued and executed within a minute interval, resulting in a skipped minute.
This seems somewhat unlikely, but not completely beyond the realms of possibility.
Related
Here is my scenario:
Player places their finger or mouse on the “Home Position” marker at the bottom of the screen.
A timer begins counting to 500ms, if the user does not lift their finger or marker in that time the holdTimerElapsed is fired.
Inside this method, we display the next marker, delay for anywhere between 500ms to 1 second (so the user has a chance to see the next target). After the delay, an audio “GO” is played and a timer is started.
Inside the timer start method:
private void StartTimer()
{
startTime = DateTime.Now;
timer.Interval = ConfigurationService.GameConfig.MarkerTimeLimit;
timer.AutoReset = false;
timer.Start();
}
We log the "start time" of those movement. If the user is able to click the next target that popped up within the alotted time (4.5 seconds) we call the stop timer method:
private void StopTimer()
{
stopTime = DateTime.Now;
timer.Stop();
}
My problem:
"Randomly" the result of:
TimeSpan time = stopTime - startTime;
Minus the 500ms hold time will be an unrealistic 2-5 milliseconds - an impossible movement time for anyone but a bot.
I am at a complete loss for why the date times would be so close together giving such a small result.
More Code:
private void HandleMarkerClick(ScatterCircle selectedCircle)
{
StopTimer();
selectedCircle.Aquired = true;
aquiredTrainingCircles.Add(selectedCircle);
TimeSpan time = stopTime - startTime;
// movementTime here 'randomly' ends up as <10ms
long movementTime = (long) time.TotalMilliseconds - ConfigurationService.GameConfig.MarkerHoldTime;
}
I am only dealing with milliseconds in this case for bench-marking movements, and they need to be relatively accurate, anything less than 100ms is generally "to fast to be real"
To put an end to this question, I took Jon Skeet's advice and switched to the Stopwatch class. The client was still having inconsistent results.
I was unable to reproduce the issue, and long story short, the client was running the application on a laptop in power saving mode which I believe was causing the inconsistencies.
Switching from power saver mode to high performance seemed to fix the issue for the most part.
Assuming I have a windows service which has a timer that is set to run every 6 hours, I would expect it to fire 4 times a day. Let's say : 0000, 0600, 1200 1800. (Military time, same as 00:00, etc...)
If the system goes to sleep at 1000, and wakes at 1700, what happens?
will it fire again at 1900, because it has 2 hours on the timer?
will it fire straight away (because it missed it's 1200 appointment), and then fire again at 2300 (adding it's 6 hours to the current time?)
I've noticed that when the computer goes to sleep, it doesn't fire the OnPause or OnContinue methods.
If anyone can shed some light on the behaviour of the system in the above cases, It'll be great know.
Cheers, and thanks in advance.
As has already been mentioned in the comments: Use the task scheduler instead of timers. See this article for further discussion.
The question of how timers behave during sleep is still interesting, though. In the specific case you mention, option 2. will be the observed behavior. The timer will fire on resume because it missed an event during sleep and subsequently start counting from 0 again The next time it fires will thus be at 23:00. This answer has sample code to support the observation.
In case you want to detect when the system sleeps and resumes, subscribe to the SystemEvents.PowerModeChanged event. This event's PowerModeChangedEventArgs contains a Mode, of which you are interested in Suspend and Resume.
For my needs, I ended up going with a windows service that will check if and when next operation needs to be carried, and simply set the timer to that time.
The windows service will update that time upon resuming from sleep.
The benefits are :
Unaffected by sleep/wake times
no console apps being run by a scheduler.
using NLog (quick tutorial here) and Growl (how to use Growl with NLog tutorial here) to receive notifications on the desktop
having a log on the system as well
Since my case is simple, having the functionality is already in a separate dll, I don't have any issues with stability or memory leaks (and if I do, shame on me). This keeps what I need happening once a day, or once every time the computer wakes up, and doesn't incur extra overhead on the system.
Like Henrik replied and linked, the correct answer is number 2.
I've wrote the following in linqpad, which is similar to the link in the above answer:
static int counter = 0;
static System.Timers.Timer my_timer;
void Main()
{
// Set up a timer to trigger every minute.
my_timer = new System.Timers.Timer();
DateTime now = DateTime.Now;
my_timer.Interval = (60 - now.Second) * 1000; // Fire at beginning of minute
string.Format("First tick in {0} seconds", my_timer.Interval/1000).Dump();
my_timer.Elapsed += OnTimer;
my_timer.Start();
while (counter < 5) { // sleep away until 5 ticks happen
Thread.Sleep(5000);
}
// stop timer and say goodbye
my_timer.Stop();
DateTime.Now.Dump("Finished running, shutting down");
}
// Print time and counter every timer tick
void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
if (my_timer.Interval != 60000) // set to one minute after first time
my_timer.Interval = 60000;
DateTime.Now.ToString("HH:mm:ss.fff").Dump("On Timer fired:");
(counter++).Dump("Static counter :");
}
Getting the results:
First tick in: 37 seconds
On Timer fired : 08:47:00.552
Static counter : 0
On Timer fired : 08:48:00.557
Static counter : 1
On Timer fired : 08:49:00.571
Static counter : 2
// Shut computer down for 3 minutes at 08:49:30
On Timer fired : 08:52:33.509
Static counter : 3
On Timer fired : 08:53:33.510
Static counter : 4
Finished running, shutting down
1/09/2014 8:53:38 AM
So, obviously the computer knows it missed a tick, it fires the method once, and continues from there. Note that it only fires once.
But would be happy if someone who knows what happens behind the scenes can shed some more light on this.
I'm writing a code where:
I.)
The user adds "events" during run-time. (To a flowlayoutpanel) These events are turning some LEDs on/off, after "x" time has elapsed and the LED-turning functions are written in a Led-function.cs class.
i.e:
1) Turn left led on After 3500ms
2) Turn right led on After 4000ms
II.)
When the user hits start a timer starts.
// Create timer.
System.Timers.Timer _timer;
_timer = new System.Timers.Timer();
_timer.Interval = (1);
_timer.Elapsed += (sender, e) => { HandleTimerElapsed(LedObject, device, _timer); };
_timer.Start();
III.)
The timer's tick event is raised every millisecond and checks if the user definied time has ellapsed. Im measuring the elapsed time with adding +1 to an integer at every tick event. (NumberOfTicks++;)
//Timer Handle
private void HandleTimerElapsed(Led_Functions LedObject, string device, System.Timers.Timer _timer)
{
NumberOfTicks++;
if (NumberOfTicks >= Start_time[0])
{
LedObject.LeftLED_ONnobutton(device);
}
}
IV.) What I noticed was that when the tick was set to 1. (So the tick event is raised every millisecond) Even if I set 3000ms to the evet the LED actually flashed around 6 seconds.
When the tick was set to 100. (So every 0,1s) then the flash was more accurate (3,5sec or so).
Any Ideas why im having this delay in time?
Or do you have any ideas how could I implement it better?
Thank you!
1ms is a really small interval for CPUs. You cannot ensure your code get called every 1ms especially when the system has some heavy work to do.
A better implement is to use DateTime.Now - startTime to get the time span or use Stopwatch.
private Stopwatch stopwatch = new Stopwatch();
// start the stopwatch:
stopwatch.Start();
// Timer Handle:
numberOfTicks = stopwatch.ElapsedMilliseconds;
I am developping a Windows Service that has to execute a method at a specific exact time.
When the service starts, it extracts several different DateTimes from an SQL Server database and should then start a thread for each DateTime. Each thread should wait until the exact DateTime value, then do some work, then wait again for a shorter period of time and then do some final work again.
I don't want to use System.Timers.Timer because:
the method has to be executed at the exact specified time
this exact time could be in more than 24h
I need to pass a parameter to the Elapsed event
How can I implement this?
Thank you.
EDIT: I just had an idea last night, what if I write a dynamic polling timer? For exemple, if the due datetime is in more than 12 hours it can poll the time every hour to re-synchronize. Then if the due datetime is in more than 3 hours it can poll the time every 30min and so on... What do you think? Would that be a bad code to write?
Thank you again.
You can't pass a parameter to the tick event with System.Timers.Timer, but you can with System.Threading.Timer. The delay time "greater than 24 hours" is no problem. The timers use a 32 bit period that is expressed in milliseconds. 2^31 milliseconds works out to something like 24.85 days. There's also an overload that lets you specify the delay with a 64-bit signed integer. 2^63 milliseconds is ... several hundred million years.
But having those timers tick at an exact date/time far in the future is problematic because you have to specify the delay time, and a clock change will cause your delay to be too short or too long (think Daylight Saving Time, or user-initiated time changes). You can specify the tick time and have a timer poll the current time every second. It's kind of ugly, but it works.
Another option is to use the Windows Waitable Timer object, which lets you set an exact date and time. Unfortunately, the Framework doesn't include a corresponding object. I wrote an article about it some years ago and published the code. The article is no longer available online, but you can download the code from http://mischel.com/pubs/waitabletimer.zip.
I have used something called ManualResetEvent in the past with a lot of success. Assuming that you know the exact time to run your code then you will be able to calculate estimated time to run (TTR) and subsequent runs should be configured within the first run.
partial class SomeService : ServiceBase
{
private ManualResetEvent stop = new ManualResetEvent(false);
private List<DateTime> times;
private int idxDT = 0;
public SomeService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.stop.Reset();
//implement you logic to calculate miliseconds to desired first run time
int miliseconds_to_run = 1;
ThreadPool.RegisterWaitForSingleObject(this.stop,
new WaitOrTimerCallback(ThreadFunc),
null,
miliseconds_to_run,
true);
}
private void ThreadFunc(object _state, bool _timedOut)
{
if (_timedOut)
{
if(this.times == null)
{
//get a list of times to run, store it along with the index of current TTR
this.times = new List<DateTime>();
}
int miliseconds_to_run = (this.times[this.idxDT++] - DateTime.Now).Miliseconds;
ThreadPool.RegisterWaitForSingleObject(this.stop,
new WaitOrTimerCallback(ThreadFunc),
null,
miliseconds_to_run,
true);
}
}
protected override void OnStop()
{
this.stop.Set();
}
}
Of course this highly depends how exact your job start time has to be. ThreadPool class will send a Thread alocation request to the OS, and then it will wait for the next available Thread from the Pool. In some processes with lots of lots of threads this could lead to Thread starvation and your exact times will be late.
You could also try creating Task Scheduler Jobs from .NET but I've never done that before.
Even though you said you don't want to use System.Timers.Timer I'll show you how to do it anyway, as bullet 1 and two in your question don't seem to be valid points against using it in my opinion.
So here's what I do in several applications of mine:
// 1. Create the timer
System.Timers.Timer timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += ...;
// 2. Calculate the number of milliseconds between the scheduled time and the current time
timer.Interval = (scheduledDate - DateTime.Now).TotalMilliSeconds;
// 3. Start the timer
timer.Start();
Done. The event will fire "roughly" at the desired time. Please note that this doesn't work down to the exact millisecond, as Windows is not a real-time OS.
I did face sort-off similar issue and used below solution which might solve your issue.
I used ManualResetEvent class, added a Wait method and made the service wait for the exact time.
protected ManualResetEvent waitEvent = new ManualResetEvent(false);
protected bool Wait(int milliSecs)
{
return !this.waitEvent.WaitOne(milliSecs, true);
}
I used this Wait in OnStart method as below:
protected override void OnStart(string[] args)
{
DateTime nextRun = dt;//datetime from the database
YourProcessOrThreadToRun process = new YourProcessOrThreadToRun();
while (Wait((int)nextRun.Subtract(DateTime.Now).TotalMilliseconds))
{
process.StartProcess();
}
}
YourProcessOrThreadToRun is the thread you want to run on that exact time.
Is there a way to execute a periodic task/thread in C# without the using of a thread pool (this is one of the main requirements I have).
The expected scenario is as the following:
The periodic thread blocks/waits for a timer event (from the system).
The system notifies the thread when the timer expires.
The thread executes some code.
The thread blocks/waits for the next timer event from the system (note that if the thread missed one or more timer events, this is ok).
The closest thing I found to this is the System.Forms.Timer, but the issue is that its accuracy is limited to 55ms which is not enough for me.
The System.Timers.Timer seems to be able to handle this via the SynchronizingObject property. However, I'm not really sure how to implement a ISynchronizeInvoke according to the above scenario. All of the code samples I found for implementing ISynchronizeInvoke seem too complicated for handling such a simple scenario.
Is there a way to easily implement this feature in C# as in the above scenario (without using threadpools) and more accurate than the System.Forms.Timer?
Windows timers have a default resolution of 15.6 ms, from their documentation:
The default system-wide timer resolution in Windows is 15.6 ms, which
means that every 15.6 ms the operating system receives a clock
interrupt from the system timer hardware. When the clock interrupt
fires, Windows updates the timer tick count and checks whether a
scheduled timer object has expired. Some applications require that
timer expiration is serviced more frequently than once every 15.6 ms.
They also state:
Applications can call timeBeginPeriod to increase the timer
resolution. The maximum resolution of 1 ms is used to support
graphical animations, audio playback, or video playback. This not only
increases the timer resolution for the application to 1 ms, but also
affects the global system timer resolution, because Windows uses at
least the highest resolution (that is, the lowest interval) that any
application requests. Therefore, if only one application requests a
timer resolution of 1 ms, the system timer sets the interval (also
called the “system timer tick”) to at least 1 ms. For more
information, see “timeBeginPeriod Function” on the MSDN® website.
So if you really need high resolution timers, you can use the timeBeginPeriod call to affect the global system timer, but know that it will affect the batter life/power consuption of the device on which it is working.
Also, there are the QueryPerformanceCounter and QueryPerformanceFrequency calls that can be used to get lower levels of precision in .net, like in this example: http://www.codeproject.com/Articles/571289/Obtaining-Microsecond-Precision-in-NET
Multimedia Timers will provide you with the highest resolution of all timers. If you really and truly need 10ms or less resolution, that will be the only way to go.
If you find that you do not need the resolution provided by Multimedia Timers, you will find that Waitable Timers will give you the ability to code a loop that waits for a timer to expire within a single thread.
You also may choose Timer Queues which provide a large number of timers without the resource overhead of the other timers, but by default uses the system thread pool.
Have you tried to simply sleep your thread?
int msecSleepTime = 25; // number of milliseconds to sleep
Thread.Sleep(msecSleepTime); // sleep the current thread for the given number of milliseconds
Quickest response from System.Timers.Timer on my system w/o reconfiguring the system's timer is ~16 ms. Set your Timer.Interval value to (int)( target interval / 16 ) * 16 then have the thread sleep for the remaining duration (and if you really need better accuracy, an interpreted language such as C# is not the correct choice):
class Program
{
private static Timer _timer = new Timer();
private static DateTime _last = DateTime.Now;
private const int IntendedInterval = 25;
static void Main(string[] args)
{
_timer.AutoReset = false;
_timer.Interval = (int)(IntendedInterval / 16) * 16;
_timer.Elapsed += _timer_Elapsed;
_timer.Start();
Console.ReadLine();
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
var now = DateTime.Now;
var duration = now - _last;
var sleep = IntendedInterval - duration.TotalMilliseconds;
if (0 < sleep )
{
System.Threading.Thread.Sleep(( int )sleep);
}
_timer.Start();
now = DateTime.Now;
duration = now - _last;
_last = now;
Console.WriteLine(duration.TotalMilliseconds.ToString());
}
}