为什么我的 MacOS 应用程序在打瞌睡,尽管我指示它不要打瞌睡

Ash*_*Ash 2 macos xamarin.mac

虽然这是在 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

zrz*_*zka 5

您没有指示您的应用程序避免小睡。正确的选项是:

\n\n

userInitiated

\n\n
\n

指示应用程序正在执行用户请求的操作的标志。

\n
\n\n

userInitiatedAllowingIdleSystemSleep

\n\n
\n

指示应用程序正在执行用户请求的操作的标志,但系统可以在空闲时休眠。

\n
\n\n

扩展App Nap文档:

\n\n
\n

如果应用程序未执行用户启动的工作(例如更新屏幕上的内容、播放音乐或下载文件),系统可能会将应用程序置于 App Nap 中。

\n
\n\n

您的应用程序正在使用background

\n\n
\n

标志表明应用程序已启动某种工作,但不作为用户请求的直接结果

\n
\n\n

再次查看文档...

\n\n
\n

App Nap 通过调节 app\xe2\x80\x99s CPU 使用率降低其计时器的触发频率来节省电池寿命。

\n
\n\n

...这就是您可能看到的结果。

\n\n
\n\n

即使我指定了LatencyCriticial,系统仍然可以让我的应用程序小睡,因为我只指定了Background?

\n\n

是的。你可以简单地自己检查一下。运行您的应用程序,打开“活动监视器”,右键单击表格标题行并添加“应用程序午睡防止睡眠”列。让您的应用程序运行一段时间,几分钟就足够了,然后检查这些列值。

\n\n

本质上,App Nap 的条件是否简化为:如果不是用户启动且不更新视图,则可能会使其打盹?

\n\n

不行,查一下文档。

\n\n
\n

一般来说,如果满足以下条件,则应用程序可以成为 App Nap 的候选者:

\n\n
    \n
  • 它不是\xe2\x80\x99t 前台应用程序
  • \n
  • 它最近没有更新窗口可见部分中的内容
  • \n
  • 听不到\xe2\x80\x99t 的声音
  • \n
  • 它没有\xe2\x80\x99t采取任何IOKit电源管理或NSProcessInfo断言
  • \n
  • 它是\xe2\x80\x99t 使用OpenGL
  • \n
\n\n

当满足上述条件时,OS X 可能会将应用程序放入 App Nap 中。

\n
\n\n

另请注意差异 - may put != will put , ... 其背后的启发式方法,其行为在不同的 macOS 版本上可能略有不同。

\n\n

我的应用程序在打开时会运行多个进程,这些进程都不是用户启动的,但对于用户不间断地运行很重要,因此,如果我保留它的配置,但使其更新视图作为定期计时器的一部分,它应该免除 App Nap 吗?

\n\n

我不会过多关注用户发起的话语。userInitiated文档说:

\n\n
\n

指示应用程序正在执行用户请求的操作的标志。

\n
\n\n

它基本上意味着用户正在等待的任何事情。如果您正在更新 UI,例如,基于用户不是通过某个按钮启动的某些任务的输出,它仍然可以是用户请求的操作(用户启动您的应用程序以获取一些结果,.. .)。

\n\n

更多信息

\n\n

我不知道你的应用程序应该做什么 -> 很难推荐任何实现它的方法。但我强烈建议观看:

\n\n\n\n

读书:

\n\n\n\n

即使这些演示文稿很旧,它也是一个存档文档,...它仍然有效并且包含许多有用的信息。

\n