问题
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
回答1:
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:
- Building Efficient OS X Apps
- Efficient Design with XPC
To read:
- Prioritize Work at the App Level
- Prioritize Work at the Task Level
Even if these presentations are old, it's an archived documentation, ... it's still valid and contains lot of useful info.
来源:https://stackoverflow.com/questions/61774220/why-is-my-macos-app-napping-despite-me-instructing-it-not-to