Smart Home Smart Home - 1 month ago 19
Objective-C Question

dispatch_after not always working

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");
});

Answer
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.

Comments