Re: NSPostWhenIdle not doing its job?
Re: NSPostWhenIdle not doing its job?
- Subject: Re: NSPostWhenIdle not doing its job?
- From: Jonathan Taylor <email@hidden>
- Date: Mon, 16 May 2011 10:50:06 +0100
Thanks very much for your reply Ken, very helpful indeed.
>> The problem can be summarised as: in spite of having a backlog of notifications building up on the main thread, NSPostWhenIdle-qualified notifications do seem to be making it through. This is causing me problems because this idle work is swallowing up main thread time, making the backlog even worse! I am trying to understand why this is happening and whether I can do anything to alleviate the situation.
>
> I suspect you have assumed things about NSPostWhenIdle and NSPostASAP which just aren't true. In particular, you think that the former is "prioritized" lower than the latter. However, they just indicate different points during a run loop's execution when the notifications are delivered.
>
> Notifications queued with NSPostWhenIdle are posted when the run loop is idle -- when it would otherwise put the thread to sleep waiting for something to happen. Those queued with NSPostASAP are posted after an input source or timer is serviced (when it's handling function or method returns).
>
> If no input sources or timers are firing, then notifications posted with NSPostASAP may not fire soon. Unfortunately, operations being queued or run in the main queue don't count, it would seem. At least, I think that's what's happening.
The (indirect) references I was working from were:
http://www.gnu.org/software/gnustep/resources/OpenStepSpec/FoundationKit/Classes/NSNotificationQueue.html
Admittedly not OS X, but presumably very closely related? Describes a usage scenario for NSPostWhenIdle that seems exactly analogous to mine.
http://www.mikeash.com/pyblog/friday-qa-2010-01-08-nsnotificationqueue.html
Again, describes an analogous situation in my view. The only difference in both cases to my situation is that their example scenarios are user-event driven, which may from what you say make a difference for some reason?
> You may also be running into this issue, somehow: <https://devforums.apple.com/message/111998#111998>. NSOperationQueue's +mainQueue presumably uses dispatch_get_main_queue() under the hood.
Hmm. That's an interesting one - if I read it correctly there are some outstanding issues with the scheduler that might be relevant to what I'm doing.
> One obvious improvement to your scheme is, since Function C should not do anything unless and until Function B has processed a new frame image, post its notification (notification 2) from Function B, not Function A. (Or otherwise arrange for Function C to be triggered by Function B's completion.)
Hmm, well spotted!
> Still, that won't help if Function B is not being called as often as you expect because NSPostASAP doesn't work like you thought. I suspect that it is only being called when something else tickles the run loop, like user events. I wonder if you click-and-hold in your window (not necessarily on a button or any active control) and just keep dragging the mouse back and forth, if that helps keep the backlog clear. (Simple mouse moves without the mouse button don't send events unless your window has specifically subscribed to them using NSTrackingArea or -setAcceptsMouseMovedEvents:.)
I've got to be honest, I was very skeptical of this but that is indeed exactly what happens. Bizarre! I wonder if this then suggests a workaround (admittedly a hideous one) of manually posting "user" events to the main loop!?
I guess (as is so often the case!) I should also be asking the broader question - how can I achieve the result I want? I have CPU-intensive code that must keep up with the rate at which data is arriving, and I also have GUI-related code that it would be nice to execute if there are any spare cycles. My understanding is:
- Although I thought notifications were a nice tool to use for what I am doing, they don't seem to be designed for quite what I am using them for. No doubt somebody somewhere knows a good reason why the specific behaviour I am seeing was chosen!
- I am not aware of a way of running code *on*the*main*thread* at low priority (i.e. will not run unless there are "spare" cycles). While GCD has a concept of low priority queues this applies to custom queues, not the main thread where GUI-related code must (I think...) run.
It would not be too hard for me to write my own scheduler which could prioritize the "important" work over the GUI updates, but this really does seem like it shouldn't be necessary! This feels like a fairly common problem to me, so I can't help feeling there must be a standard solution in the cocoa APIs that I am missing...
Thanks again
Jonny_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden