可靠地检测计算机是否要进入睡眠状态 [英] Reliably detect if computer is going to sleep
问题描述
我们正在为Mac编写一个Swift应用程序,其中我们需要检测计算机的睡眠时间戳.
We're writing a Swift Application for mac where we need to detect computer's sleep timestamps.
我们发现 NSWorkspace.willSleepNotification
和 NSWorkspace.didWakeNotification
不够可靠,因为在极少数情况下会调用 NSWorkspace.willSleepNotification
仅在PC唤醒并能够处理当前堆栈之后.您还有其他建议吗?
We have figured out NSWorkspace.willSleepNotification
and NSWorkspace.didWakeNotification
are not reliable enough, because at rare occasions NSWorkspace.willSleepNotification
would be called only after the PC wakes up and is able to process the current stack. Do you have any other suggestions?
推荐答案
查看了10.14.2上的AppKit的反汇编之后,我发现 NSWorkspace.willSleepNotification
在较低的顶部实现级IOKit IORegisterForSystemPower
API.因此,对于大多数用例而言,使用更高级别的AppKit API就足够了.
After looking at the disassembly of AppKit on 10.14.2, I have found that NSWorkspace.willSleepNotification
is implemented on top of the lower-level IOKit IORegisterForSystemPower
API. Therefore, using the higher-level AppKit API should be sufficient for most use cases.
一个棘手的问题是,AppKit将使用 CFRunLoopPerformBlock
和 kCFRunLoopCommonModes
将通知的发布放入主运行循环.因此,如果您的主线程被阻塞,或者如果主运行循环当前正在以一种非常见模式的模式运行,那么通知的发布将被延迟.但是,电源管理系统会给每个进程30秒以响应通知,因此应用程序被阻塞的可能性很小,以至于它可能在计算机进入睡眠状态之前错过通知.(如果可能发生 ,则应重新构建该应用程序,以确保它始终不会阻塞主线程.)
One gotcha is that AppKit will enqueue the posting of the notification on the main run loop using CFRunLoopPerformBlock
with kCFRunLoopCommonModes
. Therefore, if your main thread is blocked or if the main run loop is currently running in a mode that is not one of the common modes, then the posting of the notification will be delayed. However, the power management system gives each process 30 seconds to respond to the notification, so it is highly unlikely that an app would be so blocked that it could miss the notification before the computer sleeps. (If it is likely to happen, then the app should be re-architected to not block the main thread anyways.)
这篇关于可靠地检测计算机是否要进入睡眠状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!