eks*_*pto 12 macos cocoa multithreading objective-c osx-mavericks
我有一个后台应用程序,需要每1.5秒向另一个进程发送一个keep-alive.在OSX 10.7和10.8中一切都运行顺畅,但在OSX 10.9下,许多保持活动通知都会丢失,有时会达到3次.通常情况下,前3或4分钟一切正常,然后问题就开始发生了.
经过进一步检查,似乎OSX Mavericks"定时器合并"功能将负责决定将请求的1.5秒延长到4.0秒.
有没有办法在NSThread中表明不合并?或者至少表明允许的最大合并变化?
请参阅以下代码以供参考:
+(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];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Apple开发者论坛上的用户实际上建议我观看来自WWDC 2013的视频"用App Nap提高电源效率"; 我在其中找到了解决方案:
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);
}
Run Code Online (Sandbox Code Playgroud)
无论LSUIElement状态如何,这段代码都将以1.5秒(给出或持续0.5秒)触发计时器,并且将阻止App Nap仅为该计时器启动.
听起来你在没有设置适当的.plist密钥的情况下运行后台应用程序.
如果您正在使用后台应用程序,那么您必须在应用程序的plist 中将'Application is agent(UIElement)'(LSUIElement)选项设置为YES或将'Application is background only'(LSBackgroundOnly)选项设置为yes,否则它将成为主题到App Nap,这是你在这种情况下遇到的.我不希望定时器合并在定时器间隔中产生巨大的间隙.
LSUIElement适用于可能只有浮动窗口或状态栏项目的应用程序.他们没有菜单栏,他们没有得到停靠图标.
App Nap旨在影响前期用户应用程序.根据文档,有4件事会导致应用程序被发送到app-nap:
如果要阻止用户应用程序遇到App nap,则必须遵循其中一种受支持的机制,以使其中一个状态不活动.
如果您使用IOPmlib.h API,您可以为您的应用程序创建电源管理断言,这将阻止应用程序休息.
另外,您可以使用以下命令禁用自动终止:
[[NSProcessInfo processInfo] disableAutomaticTermination:@"Good Reason"];
Run Code Online (Sandbox Code Playgroud)
并再次启用自动终止:
[[NSProcessInfo processInfo] enableAutomaticTermination:@"Good Reason"];
Run Code Online (Sandbox Code Playgroud)
但这通常是针对需要在应用被视为"良好停止"(例如写出偏好)之前完成的代码.
Apple会在文档中的某个位置声明,如果您的应用程序遇到与app nap相关的问题,您应该提交雷达,以便确定它是否是实施中的错误.