为什么我指示我的MacOS App不能小睡 [英] Why is my MacOS App Napping despite me instructing it not to

查看:100
本文介绍了为什么我指示我的MacOS App不能小睡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管这是在Xamarin.Mac项目中发生的,但我认为问题更多与MacOS有关,因为迹象表明是App Nap.

在我的 AppDelegate.cs 文件中,我有以下内容:

 公共重写void DidFinishLaunching(NSNotification通知){_activity = NSProcessInfo.ProcessInfo.BeginActivity(NSActivityOptions.Background |NSActivityOptions.LatencyCritical,您为此笔记本电脑收取了$ 3,500AUD,但"无法提供足够的资源来顺利实现" +此应用程序是否在后台运行?" +吃一个d#@ k苹果.");//... 

我用每隔〜1秒运行一次的内容测试了以上内容:

  var现在= DateTime.Now;var now_str = now.ToString("HH:mm:ss.fff");Debug.WriteLine(now_str);var idle_time = now-_prevTime;如果(idle_time.TotalMilliseconds> 1200){Debug.WriteLine("FFSake Apple!");}_prevTime =现在;等待Task.Delay(1000);//是的,我知道计时器不精确,所以为什么我说〜" 1s. 

经过数小时的敲打,我决定运行该应用程序,将其放在后台,然后小睡一会.事实证明,我的应用程序也是如此.在我留下的1.5个小时中,它执行了以下操作:

  19:23:29.04019:23:30.04119:56:07.176FFF使苹果公司!19:56:08.19619:56:09.196... 

一个半小时的延迟!

问题1:为什么?
问题2:我该如何解决?

复制:: https://github.com/FunkyLambda/AppNapRepro

解决方案

您并未指示您的应用程序避免打apping.正确的选项是:

userInitiated :

标记,表明应用程序正在执行用户请求的操作.

userInitiatedAllowingIdleSystemSleep :

标记,指示应用程序正在执行用户请求的操作,但系统可以在空闲状态下进入睡眠状态.

扩展App Nap 文档:

如果某个应用未执行用户启动的工作,例如更新屏幕上的内容,播放音乐或下载文件,则系统可能会将其置于应用小憩"中.

您的应用正在使用背景:

标记以指示应用程序已启动某种工作,但并非是用户请求的直接结果.

还有文档...

App Nap通过调节应用程序的CPU使用率减少触发其计时器的频率来节省电池寿命.

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


即使我指定了 LatencyCriticial ,由于我只指定了 Background ?

是的.您可以自己检查.运行您的应用程序,打开活动监视器",右键单击表格标题行,然后添加 App Nap &防止睡眠列.让您的应用程序运行一会儿,几分钟就足够了,然后检查这些列值.

从本质上讲,App Nap的条件是否可以简化为:如果不是用户启动的并且没有更新视图,则可能会使其小睡?

不是,请查看文档.

通常,在以下情况下,一个应用可以作为应用小憩的候选者:

  • 这不是前台应用
  • 它最近没有更新窗口可见部分中的内容
  • 听不到
  • 它没有执行任何IOKit电源管理或NSProcessInfo断言
  • 它没有使用OpenGL

满足上述条件时,OS X可能会将应用程序置于App Nap中.

还请注意区别-可能放!= 将放,...启发式算法,其行为在不同的macOS版本上可能会略有不同.

我的应用程序在打开时会运行多个进程,这些进程都不是用户启动的,但是对于用户连续运行至关重要,因此,如果我将其保留在配置中,则可以使它作为部分更新视图定期计时器,应该将其从App Nap中排除吗?

我不会过多地关注用户启动的单词. userInitiated 文档说:

标记,指示应用程序正在执行用户请求的操作.

这基本上意味着用户正在等待的任何内容.而且,如果要更新UI,则基于用户未通过某些按钮启动的某些任务的输出,例如,它仍然可以是用户请求的操作(用户启动了您的应用以获取一些结果,...)

更多信息

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

阅读:

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

Although this is happening within a Xamarin.Mac project, I think the issue is more to do with MacOS, as the signs are that of App Nap.

In my AppDelegate.cs file, I have this:

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."
                );
    // ...

I tested the above with the following that runs every ~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.

After hours of banging my head, I decided to run the app, put it in the background and go have a nap. Turns out, so did my app. In the 1.5 hours I left it on, it did this:

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

A lag of over half an hour!

Question 1: Why?
Question 2: How do I get around this?

Repro: https://github.com/FunkyLambda/AppNapRepro

解决方案

You didn't instruct your app to avoid napping. The correct options are:

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 documentation:

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.

Your app is using background:

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

And the documentation again ...

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

... which is what you probably see as a result.


Even if I specify LatencyCriticial, the system can still make my app nap, because I've only specified Background?

Yes. You can simply check it by yourself. Run your app, open Activity Monitor, right click on the table header row and add the App Nap & Preventing Sleep columns. Keep your app running for a while, couple of minutes are enough, and then check these column values.

Essentially, does the condition for App Nap simplify to: if not user-initiated and it's not updating view, it may be made to nap?

Nope, check the documentation.

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.

Also notice the difference - may put != will put, ... Heuristic behind it and it the behavior can slightly differ on different macOS versions.

My app when opened runs several processes, none of which are user initiated, but important for the user to have running without interruption, so if I leave it with the configuration I have but make it update the view as part of the periodic timer, it should be exempted from App Nap?

I wouldn't focus too much on user initiated words. userInitiated docs says:

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

It basically means anything that user is waiting for. And if you're updating UI, based on outputs of some tasks that weren't initiated by the user via some button for example, it can still be user-requested action (user launched your app to get some results, ...).

More info

I don't know what your app is supposed to do -> it's hard to recommend any approach how to achieve it. But I'd highly recommend to watch:

To read:

Even if these presentations are old, it's an archived documentation, ... it's still valid and contains lot of useful info.

这篇关于为什么我指示我的MacOS App不能小睡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆