为什么我的 MacOS 应用程序在休眠,尽管我指示它不要休眠

Why is my MacOS App Napping despite me instructing it not to

虽然这发生在一个 Xamarin.Mac 项目中,但我认为这个问题更多地与 MacOS 有关,因为迹象是 App Nap。

在我的 AppDelegate.cs 文件中,我有这个:

public override void DidFinishLaunching(NSNotification notification)
{
    _activity = NSProcessInfo.ProcessInfo.BeginActivity(
                    NSActivityOptions.Background |
                    NSActivityOptions.LatencyCritical,
                    "You charge ,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."
                );
    // ...

我用下面的方法测试了上面的内容 运行s 每 ~1s:

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.

经过数小时的撞击,我决定 运行 应用程序,将其置于后台并小睡一会儿。事实证明,我的应用程序也是如此。在我打开它的 1.5 小时内,它做了这个:

19:23:29.040
19:23:30.041
19:56:07.176
FFSakes Apple!
19:56:08.196
19:56:09.196
...

延迟半个多小时!

问题一:为什么?
问题 2:我该如何解决这个问题?

转载: https://github.com/FunkyLambda/AppNapRepro

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

userInitiated:

Flag to indicate the app is performing a user-requested action.

userInitiatedAllowingIdleSystemSleep:

Flag to indicate the app is performing a user-requested action, but that the system can sleep on idle.

Extend App Nap 文档:

If an app isn’t performing user-initiated work such as updating content on screen, playing music, or downloading a file, the system may put the app in App Nap.

您的应用正在使用 background

Flag to indicate the app has initiated some kind of work, but not as the direct result of user request.

还有文档...

App Nap conserves battery life by regulating the app’s CPU usage and by reducing the frequency with which its timers are fired.

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


即使我指定了LatencyCriticial,系统仍然可以让我的应用休眠,因为我只指定了Background?

是的。您可以自己检查一下。 运行 您的应用程序,打开 Activity 监视器,右键单击 table header 行并添加 App Nap & 防止睡眠 列。将您的应用 运行 保留一段时间,几分钟就足够了,然后检查这些列值。

从本质上讲,App Nap 的条件是否简化为:如果不是user-initiated并且它没有更新视图,它可能会打盹吗?

不,查看文档。

Generally, an app is a candidate for App Nap if:

  • It isn’t the foreground app
  • It hasn’t recently updated content in the visible portion of a window
  • It isn’t audible
  • It hasn’t taken any IOKit power management or NSProcessInfo assertions
  • It isn’t using OpenGL

When the above conditions are met, OS X may put the app in App Nap.

还要注意区别 - may put != will put, ... Heuristic behind and it the behavior can slightly different在不同的 macOS 版本上。

我的应用程序在打开时会运行多个进程,none 其中是用户启动的,但对于用户来说 运行 不间断很重要,所以如果我离开它我的配置只是让它作为定期计时器的一部分更新视图,它应该免于 App Nap?

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

Flag to indicate the app is performing a user-requested action.

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

更多信息

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

阅读:

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