I have a background application which requires to send a keep-alive to another process every 1.5 seconds. Everything works smoothly in OSX 10.7 and 10.8, but under OSX 10.9 many keep-alive notifications are missed, sometime up to 3. Usually everything works fine for the first 3 or 4 minutes then problems start to occur.
After further inspection, it seems that OSX Mavericks "Timer Coalescing" feature would be responsible for making the decision of extending the requested 1.5 seconds up to 4.0 seconds.
Is there any way to indicate in a NSThread not to coalesce? Or at the very least to indicate the maximum coalescing variations allowed?
See code below for reference:
+(void)keepAliveThread
{
@autoreleasepool {
void (^keepAlive)() = ^ (){
// (snipped!) do something...
};
dispatch_queue_t mainQueue = dispatch_get_main_queue();
while( [NSThread currentThread].isCancelled == NO )
{
@autoreleasepool {
dispatch_async(mainQueue, keepAlive);
[NSThread sleepForTimeInterval:1.5];
}
}
}
}
A user on the Apple Developer forums actually recommended I watch a video from WWDC 2013 entitled "Improving Power Efficiency with App Nap"; in which I found the solution:
static dispatch_source_t _keepAliveTimer;
+(void)enable
{
_keepAliveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_main_queue());
dispatch_source_set_event_handler(_keepAliveTimer, ^{
// do something
});
dispatch_source_set_timer(_keepAliveTimer, dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), 1.5 * NSEC_PER_SEC, 0.5 * NSEC_PER_SEC);
dispatch_resume(_keepAliveTimer);
}
This piece of code will fire a timer at 1.5 seconds (give or take 0.5 seconds) regardless of the LSUIElement state and will prevent App Nap from kicking in for that timer only.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With