0

J'ai essayé notre test simple suivant pour comprendre des questions de qualité de service dans Interaction between qualityOfService property of NSOperationQueue & NSOperation added to itdispatch_after pas toujours travailler

Tout en faisant cela, je suis en cours d'exécution dans une question bizarre, où le code dans un dispatch_after ne fonctionne toujours. Quelqu'un peut-il m'aider à comprendre pourquoi l'affaire 2 ne fonctionne pas.

Dans ce cas, le code annuler l'intérieur dispatch_after est exécuté

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

Mais dans ce cas, il ne reçoit pas exécuté

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

Répondre

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

Ce code semble très Tout comme il bloque la file d'attente principale jusqu'à la sortie de ce bloc. Si la file d'attente principale est bloquée, aucun bloc planifié dans la file d'attente principale ne sera exécuté.

+0

Merci @bbum. Vous avez raison. Si j'ajoute l'opération à une opérationQ qui n'est pas la file d'attente principale, l'annulation fonctionne. Cela fonctionne aussi, si le dispatch_after est envoyé dans une autre file d'attente. Donc, est-ce une bonne compréhension du problème: Le bloc ci-dessus s'exécute sur la file d'attente principale. Par conséquent, le bloc soumis par dispatch_after n'est jamais exécuté car il est bloqué derrière. –