I think you might be misunderstanding the meaning of isConcurrent
. This is totally understandable, since it's incredibly poorly named. When you return YES
from -isConcurrent
what it really means is "I will handle any concurrency needs associated with this operation, and will otherwise behave asynchronously." In this situation, NSOperationQueue
is free to call -start
on your operation synchronously on the thread from which you add the operation. The NSOperationQueue
is expecting that, because you've declared that you will manage your own concurrency, that your -start
method will simply kick off an asynchronous process and return right away. I suspect this is the source of your problem.
If you implemented your operation by overriding -main
then you almost certainly want to be returning NO
from isConcurrent
. To make matters more complicated, the behaviors associated with isConcurrent
have changed over the years (but all that is covered in the official docs.) A fantastic explanation of how to properly implement a returns-YES
-from-isConcurrent
NSOperation
can be found here.
The way I'm reading your question here, it doesn't sound like your NSOperation
subclass actually needs to "manage its own concurrency", but rather that you simply want it to execute asynchronously, "on a background thread", potentially "concurrently" with other operations.
In terms of assuring the best performance for your AVCaptureVideoDataOutputSampleBufferDelegate
callbacks, I would suggest making the queue you pass in to -setSampleBufferDelegate:queue:
be (itself) concurrent and that it target the high-priority global concurrent queue, like this:
dispatch_queue_t queue = dispatch_queue_create("it.CloudInTouchLabs.avsession", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
[dataOutput setSampleBufferDelegate:(id)self queue:queue];
Then you should make the delegate callback methods as lightweight as possible -- nothing more than packaging up the information you need to make the NSOperation
and add it to the NSOperationQueue
.
This should ensure that the callbacks always take precedence over the NSOperations
. (It's my understanding that NSOperationQueue
targets either the main queue (for the NSOperationQueue
that's associated with the main thread and run loop) or the default priority background queue.) This should allow your callbacks to fully keep up with the frame rate.
Another important thing to take away here (that another commenter was getting at) is that if you're doing all your concurrency using GCD, then there is only one special thread -- the main thread. Other than that, threads are just a generic resource that GCD can (and will) use interchangeably with one another. The fact that a thread with a thread ID of X was used at one point to service your delegate callback, and at another point was used to do your processing is not, in and of itself, indicative of a problem.
Hope this helps!