Reputation: 11763
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?
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.
Upvotes: 14
Views: 3565
Reputation: 11763
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 :
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 : 0On Timer fired : 08:48:00.557
Static counter : 1On 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 : 3On Timer fired : 08:53:33.510
Static counter : 4Finished 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.
Upvotes: 0
Reputation: 5787
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
.
Upvotes: 2