15

xCode 4.4.1 OSX 10.8.2, looks like [operation cancelAllOperations]; isn't working

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSOperationQueue *operation = [[NSOperationQueue alloc] init];
    [operation setMaxConcurrentOperationCount: 1];
    [operation addOperationWithBlock: ^{
        for (unsigned i=0; i < 10000000; i++) {
            printf("%i\n",i);
           }
    }];
    sleep(1);
    if ([operation operationCount] > 0) {
        [operation cancelAllOperations];
    }
}

results 9999999

Awesome
  • 153
  • 1
  • 1
  • 4

1 Answers1

30

Inside your block, particularly inside the loop, call -isCancelled on the operation. If it's true, then return.

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount: 1];

NSBlockOperation *operation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOperation = operation;
[operation addExecutionBlock: ^ {
    for (unsigned i=0; i < 10000000; i++) {
        if ([weakOperation isCancelled]) return;
        printf("%i\n",i);
    }
}];
[operationQueue addOperation:operation];

sleep(1);

if ([operationQueue operationCount] > 0) {
    [operationQueue cancelAllOperations];
}

A queue can't just stop the operation's execution arbitrarily - what if some shared resources were being used by the operation that never got cleaned up? It's your responsibility to orderly end the operation when it becomes known to be cancelled. From Apple's docs:

An operation object is responsible for calling isCancelled periodically and stopping itself if the method returns YES.

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
  • so no way do stop operation until it finish? – Awesome Sep 30 '12 at 11:20
  • There is - within the code, you check isCancelled. If it's true, then you stop executing. The operation stops itself, the queue just tells it to cancel. Does that make sense? – Carl Veazey Sep 30 '12 at 11:29
  • 4
    Worth noting that under ARC, you must make a weak reference to the operation object and use that to check for isCancelled, to avoid a retain cycle. – jrturton Sep 30 '12 at 12:09
  • @jrturton thanks for that reminder I updated my code accordingly! – Carl Veazey Oct 08 '12 at 05:55
  • Does this actually work? According to the docs for addExecutionBlock, the specified block should not make any assumptions about its execution environment. – akaru Mar 16 '13 at 01:42
  • @akaru I just re-implemented it inside a new iOS project and verified the behavior. What assumptions about the execution environment are being made? – Carl Veazey Mar 16 '13 at 02:32