The following code ticks nicely every two minutes under normal conditions:
Observable.Interval(TimeSpan.FromSeconds(120)).Subscribe(
l =>
{
var now = DateTime.Now;
Console.WriteLine(
"Tick at " + now.ToString("hh:mm:ss") + " Count " + l.ToString());
});
Behavior after device sleeps for some time and then resumes
Tick at 11:30:00 Count 0
(11:31:55 put computer to sleep)
(no tick at 11:32:00 because PC is suspended, which is fine)
(no tick at 11:34:00 because PC is suspended)
(11:34:30 wake computer up)
(no tick as soon as possible to indicate that ticks were missed)
Tick at 11:36:30 Count 1
It seems that the Observable Interval timer kind of resets itself and starts the interval anew from the time the device resumes. (I observed similar behavior with Observable Timer)
Sleep-aware timer
I need a timer that does not restart the interval on resume, but ticks once if any ticks missed during sleep
- not once for each tick missed, but once in total if any number of ticks missed
- this is especially relevant for TimeSpans of hours or days, which in some cases will make the timer never tick again if a laptop goes to sleep even once a day
- would be great to have an overload for Observable Interval and Timer that specifies such misfire instructions?
- if cannot make it work in the Rx Observable space, are there other timers out there are sleep-defiant in some configurable way?
- haven't tested Quartz yet for this, but would ideally like to not have to include more dependencies, so an Observable or managed .NET solution is preferred
- the same should work for other deeper sleep modes e.g. hibernation
Observable.Interval
during Sleep mode changes if you provide eitherNewThreadScheduler.Default
orCurrentThreadScheduler.Instance
. In this case the timer does not reset itself, but emits "slept" values once out of Sleep mode and continues with the "correct timing". Could it be possible to implement your ownIScheduler
that buffers values based on Sleep mode ? (you can detect these changes withObservable.FromEventPattern<PowerModeChangedEventHandler, PowerModeChangedEventArgs>
) – JettonObservable.Interval(TimeSpan.FromSeconds(120), NewThreadScheduler.Default)
and it did emit "slept" values, but not as soon as possible on resume but after the set 2 minute interval after resume i.e. multiple slept values together were emitted but interval was still reset Then after that normal values continued from original timing start, but that's too late still. For instance, if I resumed at 11:34:30 the "slept" values would be signalled as late as 11:36:30 and the next normal value at 11:38:00 (because I originally subscribed at 11:30:00) – VictoryPowerModeChanged
event. – JettonInterval
isn't the same as aTimer
that repeats itself. It fires once, waits for all subscribers to finish, and then schedules the next firing, and the cycle repeats. So when your machine goes to sleep it doesn't fire so it doesn't reschedule, hence you're not ever going to get "missing ticks". – Wahlstrom