congnd
congnd

Reputation: 1284

Canceled operation is still running

I need to cancel all operation in operationqueue. but after call cancellAllOperation method, operations is still running. simple example:

@interface MyOperation : NSOperation
@end
@implementation MyOperation
-(void)main {
  NSLog(@"starting 1");
  sleep(4);
  NSLog(@"finished 1");
}
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
   [super viewDidLoad];
   NSOperationQueue *queue = [[NSOperationQueue alloc] init];
   MyOperation *op = [MyOperation new];
   [queue addOperation:op];
   sleep(2);
   [queue cancelAllOperations];
   NSLog(@"canceled");
}
log:
2014-07-23 09:55:48.839 MDict1[837:1303] starting 1
2014-07-23 09:55:50.842 MDict1[837:70b] canceled
2014-07-23 09:55:52.842 MDict1[837:1303] finished 1

Upvotes: 2

Views: 778

Answers (1)

rmaddy
rmaddy

Reputation: 318864

Canceling an operation won't wake up the sleep call. And calling sleep in viewDidLoad is BAD. Never sleep on the main thread.

The proper solution is that the implementation of your operation's main method needs to check if self has been cancelled. If so, it needs to return.

One rough example might be:

- (void)main {
    while (!self.isCancelled) {
        // do some repeated operation
    }
}

Again, it is the responsibility of the operation to stop itself when it sees that it has been cancelled. The queue doesn't actually kill any operations.

From the docs for NSOperationQueue cancelAllOperations (emphasis mine):

This method sends a cancel message to all operations currently in the queue. Queued operations are cancelled before they begin executing. If an operation is already executing, it is up to that operation to recognize the cancellation and stop what it is doing.

Upvotes: 1

Related Questions