I think you may not understand the meaning of isConcurrent . This is understandable, as it is incredibly poorly named. When you return YES from -isConcurrent , what does this really mean, I "handle any concurrency needs associated with this operation, and otherwise it will behave asynchronously." In this situation, NSOperationQueue can freely call -start on your operation synchronously in the thread from which you add the operation. NSOperationQueue expects that since you stated that you will be managing your own concurrency, your -start method -start simply start the asynchronous process and return immediately. I suspect this is the source of your problem.
If you performed your operation by overriding -main , you would almost certainly want to return NO from isConcurrent . To complicate matters, the behavior associated with isConcurrent has changed over the years (but all that is described in isConcurrent papers). A fantastic explanation of how to implement return correctly - YES -from- isConcurrent NSOperation can be found here.
As I read your question here, it doesn't look like your NSOperation subclass really needs to "manage its own concurrency", but rather just wants it to execute asynchronously, "to the background thread", potentially "simultaneously" with other operations.
In terms of providing the best performance for your AVCaptureVideoDataOutputSampleBufferDelegate I would suggest making the queue you go into -setSampleBufferDelegate:queue: be (itself) at the same time and that it targets a high priority global parallel queue, for example:
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 easy as possible - just pack the information needed to create the NSOperation and add it to the NSOperationQueue .
This should ensure that callbacks always take precedence over NSOperations . (I understand that NSOperationQueue is for the main queue (for the NSOperationQueue associated with the main thread and the run loop) or the default for the background priority queue.) This should allow your callbacks to fully support the frame rate.
Another important thing that needs to be removed here (as another commentator noted) is that if you use all your concurrency using GCD, then there is only one special thread - the main thread. In addition, threads are just a common resource that a GCD can (and will) use interchangeably with each other. The fact that the thread with thread ID X was used at one point to serve the delegate callback, and at another point was used for your processing, does not in itself indicate a problem.
Hope this helps!