虽然这是在 Xamarin.Mac 项目中发生的,但我认为问题更多地与 MacOS 有关,因为迹象是 App Nap 的迹象。
在我的AppDelegate.cs文件中,我有这个:
public override void DidFinishLaunching(NSNotification notification)
{
_activity = NSProcessInfo.ProcessInfo.BeginActivity(
NSActivityOptions.Background |
NSActivityOptions.LatencyCritical,
"You charge $3,500AUD for this laptop and yet " +
"can't provide enough resources for a smooth " +
"operation of this app in the background? " +
"Eat a d#@k Apple."
);
// ...
Run Code Online (Sandbox Code Playgroud)
我使用每 ~1 秒运行一次的以下命令测试了上述内容:
var now = DateTime.Now;
var now_str = now.ToString("HH:mm:ss.fff");
Debug.WriteLine(now_str);
var idle_time = now - _prevTime;
if (idle_time.TotalMilliseconds > 1200)
{
Debug.WriteLine("FFSakes Apple!");
}
_prevTime = now;
await Task.Delay(1000); // yes yes, I know timers aren't precise, hence why I said '~'1s.
Run Code Online (Sandbox Code Playgroud)
经过几个小时的敲头之后,我决定运行该应用程序,将其置于后台,然后去小睡一会儿。事实证明,我的应用程序也是如此。在我将其打开的 1.5 小时内,它执行了以下操作:
19:23:29.040
19:23:30.041
19:56:07.176
FFSakes Apple!
19:56:08.196
19:56:09.196
...
Run Code Online (Sandbox Code Playgroud)
延迟了半个多小时!
问题1:为什么?
问题 2:我该如何解决这个问题?
重现: https: //github.com/FunkyLambda/AppNapRepro
您没有指示您的应用程序避免小睡。正确的选项是:
\n\n\n\n\n\n\n指示应用程序正在执行用户请求的操作的标志。
\n
userInitiatedAllowingIdleSystemSleep:
\n\n\n指示应用程序正在执行用户请求的操作的标志,但系统可以在空闲时休眠。
\n
扩展App Nap文档:
\n\n\n\n\n如果应用程序未执行用户启动的工作(例如更新屏幕上的内容、播放音乐或下载文件),系统可能会将应用程序置于 App Nap 中。
\n
您的应用程序正在使用background:
\n\n\n标志表明应用程序已启动某种工作,但不作为用户请求的直接结果。
\n
再次查看文档...
\n\n\n\n\nApp Nap 通过调节 app\xe2\x80\x99s CPU 使用率并降低其计时器的触发频率来节省电池寿命。
\n
...这就是您可能看到的结果。
\n\n即使我指定了LatencyCriticial,系统仍然可以让我的应用程序小睡,因为我只指定了Background?
是的。你可以简单地自己检查一下。运行您的应用程序,打开“活动监视器”,右键单击表格标题行并添加“应用程序午睡和防止睡眠”列。让您的应用程序运行一段时间,几分钟就足够了,然后检查这些列值。
\n\n本质上,App Nap 的条件是否简化为:如果不是用户启动且不更新视图,则可能会使其打盹?
\n\n不行,查一下文档。
\n\n\n\n\n一般来说,如果满足以下条件,则应用程序可以成为 App Nap 的候选者:
\n\n\n
\n\n- 它不是\xe2\x80\x99t 前台应用程序
\n- 它最近没有更新窗口可见部分中的内容
\n- 听不到\xe2\x80\x99t 的声音
\n- 它没有\xe2\x80\x99t采取任何IOKit电源管理或NSProcessInfo断言
\n- 它是\xe2\x80\x99t 使用OpenGL
\n当满足上述条件时,OS X 可能会将应用程序放入 App Nap 中。
\n
另请注意差异 - may put != will put , ... 其背后的启发式方法,其行为在不同的 macOS 版本上可能略有不同。
\n\n我的应用程序在打开时会运行多个进程,这些进程都不是用户启动的,但对于用户不间断地运行很重要,因此,如果我保留它的配置,但使其更新视图作为定期计时器的一部分,它应该免除 App Nap 吗?
\n\n我不会过多关注用户发起的话语。userInitiated文档说:
\n\n\n指示应用程序正在执行用户请求的操作的标志。
\n
它基本上意味着用户正在等待的任何事情。如果您正在更新 UI,例如,基于用户不是通过某个按钮启动的某些任务的输出,它仍然可以是用户请求的操作(用户启动您的应用程序以获取一些结果,.. .)。
\n\n更多信息
\n\n我不知道你的应用程序应该做什么 -> 很难推荐任何实现它的方法。但我强烈建议观看:
\n\n\n\n读书:
\n\n\n\n即使这些演示文稿很旧,它也是一个存档文档,...它仍然有效并且包含许多有用的信息。
\n