0

I tried our the following simple test to understand the QoS questions in Interaction between qualityOfService property of NSOperationQueue & NSOperation added to it

While doing this, I am running into a weird issue, where the code inside a dispatch_after is not always working. Can someone help me understand why the case 2 is not working.

In this case, the cancel code inside dispatch_after gets executed

  NSBlockOperation *newOp = [NSBlockOperation new];
    __weak NSBlockOperation *weakOp = newOp;
    [newOp addExecutionBlock:^{
        NSBlockOperation *innerOp = weakOp;
        while (![innerOp isCancelled])
        {
            usleep(2000000) ;
            NSLog(@"New Op QOS is %ld",innerOp.qualityOfService);
        }
        NSLog(@"Exiting snce new Op is cancelled");
    }];
    [self.myCustomQ addOperation:newOp];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSBlockOperation *innerOp = weakOp;
        [innerOp cancel];
        NSLog(@"Cancelling block 2");
    });

But in this case, it is not getting executed

self.myMainQ = [NSOperationQueue mainQueue];
NSLog(@"QOS of main Q is %ld",self.myMainQ.qualityOfService);

__weak ViewController *weakSelf = self;
self.fromMainOp = [NSBlockOperation blockOperationWithBlock:^{
    ViewController *innerSelf = weakSelf;
    while (![innerSelf.fromMainOp isCancelled])
    {
        usleep(1000000) ;
        NSLog(@"Main OP QOS is %ld",innerSelf.fromMainOp.qualityOfService);
    }
}];
NSLog(@"QOS of main op is %ld",self.fromMainOp.qualityOfService);
[self.myMainQ addOperation:self.fromMainOp];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    ViewController *innerSelf = weakSelf;
    [innerSelf.fromMainOp cancel];
    NSLog(@"Cancelling operation");
});
Community
  • 1
  • 1
Smart Home
  • 801
  • 7
  • 26

1 Answers1

4
self.fromMainOp = [NSBlockOperation blockOperationWithBlock:^{
    ViewController *innerSelf = weakSelf;
    while (![innerSelf.fromMainOp isCancelled])
    {
        usleep(1000000) ;
        NSLog(@"Main OP QOS is %ld",innerSelf.fromMainOp.qualityOfService);
    }
}];

That code looks very much like it is blocking the main queue until that block exits. If the main queue is blocked, then no blocks scheduled on the main queue are going to be executed.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • Thanks @bbum. You are correct. If I add the operation to a OperationQ that is not main queue, the cancellation works. It also works, if the dispatch_after is sent on a different queue. So, is this correct understanding of the issue: The above block is executing on main Queue. Hence, the block submitted by dispatch_after never gets executed because it is stuck behind it. – Smart Home Oct 17 '16 at 01:15