2

I am just wondering at what exact moment a completionBlock is executed on a NSOperation owned by a NSOperationQueue.

On my newest project, a client for Amazon S3 (https://github.com/StudioIstanbul/SIAFAWSClient), I use a NSOperation with a completionBlock for requests to Amazon REST API. The client is able to monitor the status of all scheduled requests via a property on the main class called isBusy. In my operation's completion block I set the value for this property to NO if there are no other operations scheduled in my NSOperationQueue. I now figured out that in some rare cases my current NSOperation is still included in my NSOperationQueue when the completionBlock gets called. This seems a little strange to me. I ended up checking for existence of the current NSOperation in my queue to fix this, but this seems unnecessary from a design point of view.

__weak AWSOperation* thisOperation = operation;
[operation setCompletionBlock:^{
    if (self.operationQueue.operationCount <= 0
      || (self.operationQueue.operationCount == 1
      && [self.operationQueue.operations objectAtIndex:0] == thisOperation)) {
        [self willChangeValueForKey:@"isBusy"];
        _isBusy = NO;
        [self didChangeValueForKey:@"isBusy"];
    }
}];

Does anybody have more information on this behavior?

Raziel
  • 444
  • 6
  • 22
Andreas Zöllner
  • 233
  • 3
  • 12

1 Answers1

0

From the docs:

The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore, you should not use this block to do any work that requires a very specific execution context.

So, you can't guarantee that it will be called before or after the operation is removed from the queue. It's sent after the trigger to remove the operation from the queue (because the operation is finished) but there is effectively a race between those 2 things.

Your best option is to push your consideration to the next iteration of the main runloop if you're interrogating the operation queue itself to determine the state.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • But this does not say that it is not guaranteed to run after operation removal. I'm surprised, too. – Amin Negm-Awad Feb 15 '16 at 15:13
  • it explicitly says there is no guarantee about exactly when it'll run, because the thread on which it will run is not guaranteed – Wain Feb 15 '16 at 15:15
  • Yes, but on whatever thread it is run it could be launched after removal. – Amin Negm-Awad Feb 15 '16 at 15:34
  • this sounds interesting, I read about the secondary thread (for this I actually do push thread relevant code to the runloop of a specified thread) but I never thought this could also mean a different time of execution. – Andreas Zöllner Feb 15 '16 at 16:44