0

我盡了下面這個簡單的測試,以瞭解Interaction between qualityOfService property of NSOperationQueue & NSOperation added to itdispatch_after並不總是工作

的服務質量問題,而這樣做,我遇到了一個奇怪的問題,其中一個dispatch_after裏面的代碼並不總是工作。有人可以幫助我理解爲什麼案例2不起作用。

在這種情況下,內部dispatch_after取消代碼被執行

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

但在這種情況下,它是沒有得到執行

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

回答

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

該代碼看起來很就像阻塞主隊列直到該塊退出一樣。如果主隊列被阻塞,則不會執行主隊列上計劃的塊。

+0

Thanks @bbum。你是對的。如果我將操作添加到不是主隊列的OperationQ中,則取消將起作用。如果dispatch_after在不同的隊列上發送,它也可以工作。那麼,對這個問題的正確理解是:上面的塊在主隊列上執行。因此,由dispatch_after提交的塊永遠不會被執行,因爲它滯留在它後面。 –