7
votes

Comment "casser" hors Dispatch_apply ()?

Y a-t-il un moyen de simuler une instruction code> code> dans un DISPATCH_APPLY () CODE> bloc?

Par exemple, chaque API de cacao que j'ai vu traiter avec Les blocs énumérants ont un paramètre "Stop": p>

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL *stop) {
    if ([obj isNotVeryNice]) {
        *stop = YES; // No more enumerating!
    } else {
        NSLog(@"%@ at %zu", obj, i);
    }
}];


0 commentaires

3 Réponses :


4
votes

Je ne pense pas que Dispatch_apply soutient cela. La meilleure façon de penser à imiter qu'il serait de faire une variable booléenne __bloc, et de le vérifier au début du bloc. Si c'est ensemble, cautionnez-vous rapidement. Vous devrez toujours courir le bloc à travers le reste des itérations, mais ce serait plus rapide.


0 commentaires

1
votes

Vous ne pouvez pas break A Dispatch_apply car il est illogique.

dans -EnumèrentObjecteBlock: Une pause est bien défini car les fonctions sont exécutées séquentiellement . Mais dans Dispatch_apply Les fonctions sont exécutées en parallèle. Cela signifie à la I = 3 RD Invocation du "bloc", le i = 4 00 appel aurait pu être démarré. Si vous break au i = 3 , si le i = 4 appel est toujours exécuté?

La réponse @BJ est la réponse Le plus proche que vous puissiez faire, mais il y aura toujours un "déversement".


3 commentaires

Eh bien, ce n'est pas tout à fait vrai; Bien qu'il soit vrai que l'énumérantObjectBlock: est séquentielle, il y a aussi énumérableObjectSwithOptions: Utilisation de Block :. Ce paramètre "Options" peut être utilisé pour diriger que l'énumération devrait se produire simultanément. Je ne suis pas sûr de savoir comment ils le font en interne, mais je suppose que cela a été fait à l'aide d'un groupe Dispatch_Proupe qui permettrait un contrôle plus direct.


Mais le point est que énumérantObjectSwithOptions: UtilisationBlock: a toujours le * paramètre d'arrêt.


Il serait logique de soutenir l'arrêt de Dispatch_Apply (), mais il n'a pas eu de sens dans les objectifs de conception. Indiquant que le drapeau d'arrêt sur énumérerObjectBlock: existe à cause de l'exécution séquentielle implicite est fausse; Les deux sont complètement orthogonaux.



14
votes

Par conception, Dispatch _ * () Code> Les API n'ont aucune notion d'annulation. La raison en est que c'est presque universellement vrai que votre code maintient le concept de quand arrêter ou non et, donc, également soutenir cela dans les API d'expédition _ * () serait redondant (et, avec une redondance vient des erreurs). Ainsi, si vous voulez "arrêter tôt" ou annuler autrement les éléments en attente d'une file d'attente d'expédition (peu importe la manière dont ils ont été en cours), vous le faites en partageant un peu d'état avec les blocs en justice qui vous permettent d'annuler. P>

__block BOOL keepGoing = YES;
dispatch_*(someQueue, ^{
    if (!keepGoing) return;
    if (weAreDoneNow) keepGoing = NO;
}


0 commentaires