2015-09-11 1 views
0

Je lisais ceci: does dispatch_async copy internal blocksComment faire nil dispatch_async sur bloc

et je veux savoir comment obtenir l'envoi-async à zéro sur le bloc, il copié sur le tas pour que le bloc peut être des déchets collectés .

Ok, donc sur la pile locale, je crée mon bloc:

MyBlock aBlock = ^{ 
     for (int i = 0; i < 10; i++) { 
      NSLog(@"holder is: %p, holder.block is %p", holder, holder.block); 
      sleep(1); 
     } 
    }; 

dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, aBlock); 

sleep(2);  // give the queue some time to start executing the block 

Le bloc continue d'exécuter simplement parce qu'il est le bloc sur le tas qui est copié par dispatch_async. C'est tout le comportement attendu. Donc, ma question est .... Y at-il un moyen de faire explicitement ce bloc sur le tas être détruit?

Ou la mémoire ARC gérera-t-elle ce bloc pour moi dès que le dispatch_async aura fini de s'exécuter, et personnellement je ne peux rien y faire?

Merci!

+0

Le bloc est toujours en cours d'exécution. Vous ne pouvez pas le détruire pendant qu'il est en cours d'exécution, mais il sera détruit quand c'est fait. – Wain

+0

alors quand le bloc dans la file d'attente est fini, ARC va le détruire correctement? Y at-il de toute façon je peux le détruire par programmation? – rtsao

+0

Voulez-vous dire que vous voulez terminer la boucle plus tôt? – Wain

Répondre

0

Pour votre question mise à jour, vous n'avez pas besoin de nil quoi que ce soit. Le bloc sur le tas est comme n'importe quel autre objet compté de référence. Votre champ d'application a une référence forte pour la durée de la portée de la variable aBlock. Et le mécanisme de répartition asynchrone contient une référence forte jusqu'à ce qu'il ait été exécuté. Quand il n'y a plus de références fortes, il est désalloué.

+0

votre déclaration: "Votre portée a une référence forte pour la durée de la portée de la variable aBlock." pouvez-vous clarifier?Voulez-vous dire: 1) bloc va sur la pile 2) certaines références de copie Object (ou dispatch_async) qui bloquent. Ainsi, ce bloc va sur le tas. 3) la pile a maintenant une forte référence au bloc sur le tas. Donc en 3), est-ce que la pile fait éclater le bloc original, et crée une référence forte au bloc dans le tas? – rtsao

+1

@rtsao: D'abord, ne vous inquiétez pas de la pile/pile et pensez-y comme toujours tas comme d'autres objets. Alors cela a du sens, n'est-ce pas? La pile/tas chose est un détail d'implémentation et tant que vous copiez un bloc au lieu de conserver, cela fonctionnera correctement. (Copier un bloc le déplace vers le tas.) ARC devrait prendre soin de la copie pour vous. – newacct

+1

@rtsao: Ce que ARC fait ici ne nous est pas connu, mais par exemple il pourrait 1) copier le bloc (en le déplaçant vers le tas) immédiatement après la définition lors de l'assignation à 'aBlock'; alors 'aBlock' serait une référence forte, et le libérerait à la fin de' aBlock'; le dispatch_async le copiera quand vous le passerez et le relâchera quand il aura fini d'exécuter le bloc. Alternativement, il pourrait 2) ne pas copier le bloc et ne pas le relâcher dans cette portée; il sera initialement sur la pile; Le dispatch_async va encore copier le bloc et le déplacer vers le tas, et le relâcher quand c'est fait. – newacct

0

vous pouvez ajouter une propriété BOOL à la blockholder de classe par exemple:

@property (nonatomic, assign, getter = isCancelled) BOOL cancelled; 

et à l'intérieur du bloc ajouter un test pour vérifier si le bloc est annulé ou pas comme ça:

__block BlockHolder * holder = [[BlockHolder alloc] init]; 
MyBlock aBlock = ^{ 
     for (int i = 0; i < 10; i++) { 
      if(holder.isCancelled) return; 
      NSLog(@"holder is: %p, holder.block is %p", holder, holder.block); 
      sleep(1); 
     } 
    }; 

et si vous voulez annuler le bloc, vous pouvez définir la valeur de annulé à OUI. J'espère que ça va vous aider

0

Si vous voulez pouvoir annuler la boucle, vous devez mettre une vérification à l'intérieur et éclater lorsque la condition n'est pas remplie. Cela pourrait être que votre objet conteneur est maintenant nul, ou il pourrait être le résultat d'un appel de méthode. Assurez-vous simplement que vous ne retenez pas ou n'influencez pas le test que vous ajoutez en le testant ...

+0

pouvez-vous donner un peu de code de démo? merci – rtsao