问题描述
尽管这是在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.正确的选项是:
userInitiatedAllowingIdleSystemSleep
:
扩展App Nap 文档:
您的应用正在使用背景
:
还有文档...
...这可能是您看到的结果.
即使我指定了 LatencyCriticial
,由于我只指定了 Background
?
是的.您可以自己检查.运行您的应用程序,打开活动监视器",右键单击表格标题行,然后添加 App Nap &防止睡眠列.让您的应用程序运行一会儿,几分钟就足够了,然后检查这些列值.
从本质上讲,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:
userInitiatedAllowingIdleSystemSleep
:
Extend App Nap documentation:
Your app is using background
:
And the documentation again ...
... 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.
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:
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不能小睡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!