I have a timer with a long period (some hours). It seems that if the Mac goes to sleep, the delay of the timer grows the delay of the sleep.
I am not sure to be clear : I set my Timer to a period of 10 hours at 8:00 . At 10:00 I put my Mac to sleep and I wake up it at 13:00 . My Timer should fire at 8:00 + 10 hours = 18:00 but it seems that it fires at 21:00 as my Mac sleep during 3 hours.
It’s annoying to do that king of test, does someone have the answer? Thanks.
Another details :
In my program, I already have a Date property which is the DateTime at which the Timer should launch the Method I want. As it’s a long period, I set the period shorter than the real delay I want. Then when the Timer Fire, it compare the actual DateTime to the wish Launch Method DateTime, and it re-ajust its own Period. But if the Mac sleep too long I’m out of the delay to re-ajust the Timer.
2 solutions : 1 - When the Mac wake up, re-ajust the Timer. But it seems it’s not easy to know that’s the Mac wake up.
2 - Fire the Timer every minutes (or more or less) and re-ajust it every time until it should really launch the method I want.
My application has a scheduling component so I have some experience with this. A timer in a helper app is set to run every minute. When the next event should happen the main application is started. This doesn’t work when the computer is asleep.
- There is an option to run the schedule as soon as the computer wakes up or is started even if the scheduled time has passed.
- You can set the Mac to become awake at predefined times. But this is only possible with administrator password. It’s only possible by day and by week. I need this by month, too, and made a feature request in the black hole (AKA Radar).
MBS Plugin has classes to get event for sleep/wakeup.
Also you should run timer with shorter time and check regularly if you reach time.
That would make sense. During sleep, the app execution is suspended. So it starts counting again when it wakes up. Instead of using a 10 hours period, you could make it a multiple one minute or so, and check if the time has elapsed against the clock.
For such long periods I wonder if LaunchD would not be able to run a helper in spite of the sleep state.
Yes, but I would suggest that you handle the math a bit differently. Rather than worry about re-adjusting the time. Create an event list sorted by time that the event should happen.
Then in the timer, loop through your list and see if the current time is greater than the event time, if so execute event and remove from list.
[quote=193763:@Sam Rowlands]Yes, but I would suggest that you handle the math a bit differently. Rather than worry about re-adjusting the time. Create an event list sorted by time that the event should happen.
Then in the timer, loop through your list and see if the current time is greater than the event time, if so execute event and remove from list.[/quote]
That’s the way to go.
- A Timer is like an order to not execute the Action Event sooner as the defined period of Time
- A Timer is “sleeping” while the OS is “sleeping”
- Because the timer runs in the Main Thread, it is delayed every time the UI is busy
That said, it’s better to execute the action event of a timer in a much shorter period. And then let the timer run through a list of “appointments” and check if it’s time to do what the App should do at that appointments time. Just make sure the timer period is shorter then the maximum allowed delay for your “appointments”.
Please excuse my weak english…
I think that’s the cleaner way, and I think it is easy indeed to know when the Mac wakes up. It’s a notification of NSWorkspace which can be caught like an event with MBS or MacOSLib (and I think I event posted an own stand-alone implementaion here last year).
But a timer not firing if Mac goes to sleep could not depend on the App Nap setting of the application?
You’re right. App Napp should be disabled for a Mac app that is supposed to run timers continously. Anyway, a sleep will still disable the timers for its duration.
I was testing this thing, because I’m interested too…
but the quick test application I have compiled doesn’t have the App Nap checkbox in its info window…
Other apps I have done with Xojo have it…
Can’t understand what makes a Xojo app ‘App Nap’ aware or not
Yes, this was discussed in another thread. I would set the preference from within the app itself this way you won’t forget to set it in the Finder.
I made a module for getting ‘app did terminate’ notifications and it was very easy to modify it to get wake notifications (changed the string NSWorkspaceDidTerminateApplicationNotification to NSWorkspaceDidWakeNotification). It would be nice to generalize the module but right now it only handles one type of notification.
Create a method to handle the notification
Sub handle_DidWake(event As Ptr)
Then install it
Now that method gets called at wakey wakey time.
(click the install button, sleep then wake and it lists the wake time)
I think this is Ulrichs notification code https://forum.xojo.com/conversation/post/181475
And Sam Rowlands wrote about notifications in xDev https://forum.xojo.com/22834-sam-rowlands-notificationcenter-is-awesome
Thank you all. I’m sure Christian’s plugging are great but I have a few (poor) donations for my softwares and I can’t spend more money (Xojo’s license is enough).
I think I will fire every 10 minutes if next launch is greater than 1 hour, and every minutes after.
I didn’t understand “Create an event list sorted by time that the event should happen.”. My program does synchronization between two folders. The user can launch the sync clicking a button, or launch it every xx minutes, or launch it at a specified time.
Then I have only one Method to launch. When done, I calculate when I have to launch the next one.
Thank you again to have confirmed me that a Timer sleep when the Mac sleep. Xojo should write that in the Help of the Timer (I didn’t see it).
You wrote that the period of a Timer is delayed when the UI is busy. But something change for some version of Xojo (1 or 2 years ago) :
Before, if I launch a Timer and I do a loop in the Main thread :
then the Timer never launch until the loop finish.
Now, the Timer fire even if the Main Thread is running. But it will be a little delayed as you explained.
Why not use Apples built in DidWakeNotification for exactly this info and tells you right when waking happens, instead of juggling a Timer that might be up to 10 minutes out?
App Nap shouldn’t stop the timers, they lose any precision and are coalesced with other times.