web-dev-qa-db-fra.com

Comment arrêter / annuler / suspendre / reprendre des tâches dans la file d'attente GCD

Comment arrêter/annuler/suspendre/reprendre des tâches dans la file d'attente GCD

Comment arrêter les opérations de file d'attente en arrière-plan? Je veux arrêter certains écrans de notre application. Et certains écrans devraient reprendre automatiquement. Alors, comment passer une file d'attente dans iOS?

Je veux dire lorsque l'utilisateur a parcouru l'heure de l'application, nous exécutons le fil d'arrière-plan dans dispatch_queue_t. Mais cela ne s'arrête jamais et reprend dans le code. Alors, comment peut-on suspendre et reprendre une file d'attente

27
lakshmanbob

Pour suspendre une file d'attente de répartition, c'est simplement dispatch_suspend(queue) dans Objective-C ou Swift 2.3, ou queue.suspend() in Swift = 3. Cela n'affecte aucune tâche en cours d'exécution, mais empêche simplement le démarrage de nouvelles tâches dans cette file d'attente. De plus, vous ne suspendez évidemment que les files d'attente que vous avez créées (pas les files d'attente globales, pas la file d'attente principale).

Pour reprendre une file d'attente de répartition, c'est dispatch_resume(queue) dans Objective-C ou Swift 2.3, ou queue.resume() in Swift 3. Il n'y a pas de concept de "reprise automatique", il vous suffit donc de le reprendre manuellement le cas échéant.

Pour passer une file d'attente de répartition, il vous suffit de passer l'objet dispatch_queue_t Que vous avez créé lorsque vous avez appelé dispatch_queue_create() dans Objective-C ou Swift 2.3, ou, dans Swift 3, l'objet DispatchQueue que vous créez avec DispatchQueue(label:) .

En termes d'annulation des tâches mises en file d'attente sur les files d'attente de répartition, il s'agit d'une nouvelle fonctionnalité d'iOS 8 et vous appelleriez dispatch_block_cancel(block) avec votre objet dispatch_block_t Dans Objective-C ou Swift 2.3, ou item.cancel() d'un DispatchWorkItem dans Swift 3. Cela annule les blocs/éléments en file d'attente qui ont pas démarré, mais n'arrête pas ceux qui sont en cours. Si vous voulez être en mesure d'interrompre un bloc/élément distribué, vous devez examiner périodiquement dispatch_block_testcancel() dans Objective-C et Swift 2.3, ou item.isCancelled in Swift 3.

L'annulation des blocs GCD est suffisamment compliquée pour que je vous réfère à la vidéo WWDC 2014 Power, Performance and Diagnostics: Quoi de neuf dans GCD et XPC , qui vous présente le concept de répartition des objets de bloc, la mise en file d'attente les, les annulant, etc. Alors que cela décrit les anciens Objective-C et Swift 2.3 API, tous les concepts sont également applicables au plus récent Swift 3 API.

Si vous souhaitez annuler des tâches, vous pouvez également envisager d'utiliser des files d'attente d'opérations, NSOperationQueue dans Objective-C ou Swift 2.3, alias OperationQueue in Swift 3, car ses opérations annulables existent depuis un certain temps et vous trouverez probablement de nombreux exemples en ligne. Il prend également en charge la limitation du degré de concurrence avec maxConcurrentOperationCount (alors qu'avec les files d'attente de répartition, vous ne pouvez choisir qu'entre série et simultané, et contrôler la concurrence plus que cela nécessite un petit effort de votre part).

Si vous utilisez des files d'attente d'opérations, vous suspendez et reprenez en modifiant la propriété suspended de la file d'attente. Et pour le faire circuler, il vous suffit de passer l'objet NSOperationQueue que vous avez instancié.


Cela dit, je vous suggère d'élargir votre question pour préciser quel type de tâches s'exécute en arrière-plan et expliquer pourquoi vous souhaitez les suspendre. Il pourrait y avoir de meilleures approches que de suspendre la file d'attente en arrière-plan.


Dans vos commentaires, vous mentionnez que vous utilisiez NSTimer, alias Timer in Swift 3. Si vous voulez arrêter un timer, appelez timer.invalidate() pour l'arrêter. Créez un nouveau NSTimer lorsque vous voulez le redémarrer.

Ou si le temporisateur s'exécute vraiment sur un thread d'arrière-plan, les temporisateurs GCD le font beaucoup plus gracieusement, évitant la sottise d'avoir à créer une boucle d'exécution sur un thread d'arrière-plan, que vous devez exécuter NSTimer sur les threads d'arrière-plan. Avec une minuterie GCD, vous pouvez la suspendre/reprendre comme vous suspendez/reprenez une file d'attente, en utilisant simplement l'objet minuterie au lieu de l'objet file d'attente.

55
Rob

Vous ne pouvez pas suspendre/annuler lors de l'utilisation d'une file d'attente GCD. Si vous avez besoin de cette fonctionnalité (et dans de nombreux cas généraux, même si vous n'en avez pas), vous devez utiliser l'API de niveau supérieur - NSOperationQueue. Ceci est construit sur GCD mais il vous donne la possibilité de contrôler le nombre de choses qui s'exécutent en même temps, de suspendre le traitement de la file d'attente et d'annuler des opérations individuelles/toutes.

4
Wain