https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

C’est la continuation de la concurrence dans les séries swift. Voir la partie 1 et la partie 2 pour comprendre les bases

Dans cette partie, nous aborderons les sujets suivants

  1. Qu’est-ce que les opérations et ses états de vie
  2. Créer un bloc, NSInvocationOperation et Opérations personnalisées pour exécuter des tâches asynchrones
  3. Comment annuler des opérations
  4. Qu’est-ce que les files d’attente d’opérations
  5. Comment ajouter des Opérations Dans Des Files d’Attente d’Opérations
  6. Comment créer des dépendances entre des Opérations
  7. Avantages des Files d’attente d’opérations Sur GCD
  8. Implémentation de groupe de répartition À l’aide de Files d’attente d’opérations

Les opérations sont manière orientée objet d’encapsuler le travail que vous souhaitez effectuer de manière asynchrone. Les opérations sont conçues pour être utilisées conjointement avec une file d’attente d’opérations ou par elles-mêmes

Un objet operation est une instance de la classe Operation or NSOperation (dans le framework Foundation) que vous utilisez pour encapsuler le travail que vous souhaitez que votre application exécute.

La classe d’opération elle-même est une classe de base abstraite qui doit être sous-classée pour effectuer tout travail utile. Bien qu’abstraite, cette classe fournit une infrastructure importante pour minimiser la quantité de travail que vous avez à faire dans vos propres sous-classes. De plus, le framework Foundation fournit deux sous-classes concrètes que vous pouvez utiliser telles quelles avec votre code existant.

État des opérations

Une opération a une machine d’état qui représente son cycle de vie. Il existe plusieurs états possibles qui se produisent à différentes parties de ce cycle de vie:

  • Quand il a été instantiated, il passera à l’état isReady.
  • Lorsque nous avons appelé la méthode start, elle passera à l’état isExecuting.
  • Lorsque la tâche finished passe à isFinished
  • Lorsque la tâche est en cours et que vous appelez cancel, elle passera à l’état isCancelled avant de passer à l’état isFinished

Il existe principalement trois façons de créer des opérations

BlockOperation (classe de béton)

Une classe que vous utilisez telle quelle pour exécuter un ou plusieurs objets de bloc simultanément. Comme il peut exécuter plusieurs blocs, un objet opération de bloc fonctionne à l’aide d’une sémantique de groupe; ce n’est que lorsque tous les blocs associés ont fini de s’exécuter que l’opération elle-même est considérée comme terminée.. Dans l’opération en bloc, vous pouvez tirer parti des dépendances d’opération, du KVO, des notifications et de l’annulation.

Comme le montre la figure 1, nous avons exécuté ce code async, ce qui signifie qu’il reviendra immédiatement mais la mauvaise nouvelle est qu’il bloquera le thread principal puisque operation.start() a été appelé sur le thread principal

Les objets d’opération s’exécutent de manière synchrone par défaut — c’est-à-dire qu’ils effectuent leur tâche dans le thread qui appelle leur méthode start.

Figure 1

Qu’est-ce que le diable est de manière synchrone et exécute un ou plusieurs objets de bloc simultanément.

Comme le montre la figure 1.0.1, comme vous pouvez le voir, les tâches / blocs ajoutés à l’opération de bloc elle-même exécutées simultanément, mais l’exécution de bloc de manière synchrone signifie qu’elle a bloqué le thread auquel start est appelé dans notre cas, il s’agit du thread principal

Figure 1.0.1

Comme le montre la figure Figure 1.0.2, puisque nous appelons la méthode de démarrage sur un autre thread, il bloquera ce thread

Figure 1.0.2

Comme le montre la figure 1.0.3, nous pouvons également ajouter un bloc d’achèvement qui s’appellera lorsque tous les blocs simultanés seront exécutés

Figure 1.0.3

Exécutez le fonctionnement du bloc Simultanément

Comme indiqué dans la figure 1.1 puisque nous appelons la méthode start() sur un thread d’arrière-plan, il effectuera sa tâche dans le thread. Il existe un moyen cool de le faire en utilisant la file d’attente d’opération et nous verrons cela plus tard.

Figure 1.1

NSInvocationOpération (Classe de béton)

Une classe que vous utilisez telle quelle pour créer un objet d’opération basé sur un objet et un sélecteur de votre application.

Dans l’objectif C, nous pouvons créer NSInvocationOperation alors qu’il n’est pas disponible dans Swift.

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW6

3. Opérations personnalisées

Le sous-classement Operation vous donne un contrôle total sur la mise en œuvre de vos propres opérations, y compris la possibilité de modifier la manière par défaut dont votre opération s’exécute et signale son état.

Comme le montre la figure 2, nous avons créé des opérations personnalisées en les sous-classant à partir de la classe de base Operation et en remplaçant sa méthode main. Lorsque vous sous-classez, vous mettez votre tâche sur la méthode main. Nous avons implémenté une opération personnalisée non concurrente et dans ce cas, nous avons bloqué le thread principal

Figure 2

Si vous prévoyez d’exécuter des opérations manuellement et que vous souhaitez toujours qu’elles s’exécutent de manière asynchrone, vous devez prendre les mesures appropriées pour vous assurer qu’elles le font. Pour ce faire, définissez votre objet operation comme une opération simultanée.

Comme le montre la figure 3, nous avons effectué les étapes suivantes pour effectuer la tâche simultanément

  1. sous-classe créée MyConcurrentQueue. Typographique: Le nom doit être MyConcurrentOperations
  2. Appelant la méthode start() appellera la méthode main() sur le thread d’arrière-plan
  3. Sur la méthode principale, nous avons défini notre tâche et une chose à noter, nous répondons également au cas d’annulation
  4. En appelant cancel lors d’une opération personnalisée passera à l’état isCancelled et brisera la boucle et comme le montre la figure 3, il n’imprimera que 39487 éléments

Figure 3

Files d’attente d’opérations

  1. Les files d’attente d’opérations sont l’abstraction de haut niveau de Cocoa sur GCD
  2. En utilisant Files d’attente d’opérations vous verrez la puissance réelle des opérations, au lieu de démarrer l’opération vous-même, vous la donnez à la file d’attente d’opérations, elle gère ensuite la planification et l’exécution.
  3. Les files d’attente d’opérations sont un moyen orienté objet d’encapsuler le travail que vous souhaitez effectuer de manière asynchrone.
  4. Vous ajoutez operations (tâches / travail) sur operation queue et nous avons discuté de la façon dont nous pouvons créer des opérations en utilisant deux méthodes.

Ajouter des opérations

Comme le montre la figure 4, nous avons créé deux opérations (en utilisant le bloc) et les avons ajoutées à la file d’attente des opérations. La file d’attente des opérations a démarré les deux opérations sur un thread d’arrière-plan et les a exécutées. Pas besoin d’appeler la méthode start() sur un thread personnalisé 🆒. Lorsque nous ajoutons une opération à la file d’attente d’opérations, elle s’exécute dès qu’elle est prête

Figure 4

Comme le montre la figure 5, nous venons d’exécuter la tâche en série ou vous pouvez dire que nous avons implémenté la file d’attente série à l’aide de files d’attente d’opérations, veuillez vous référer à ma partie 1 si vous ne savez pas ce qu’est la file d’attente série en définissant maxConcurrentOperationCount = 1

maxConcurrentOperationCount → Nombre maximal d’opérations en file d’attente pouvant s’exécuter en même temps. La valeur par défaut est -1, ce qui signifie que le système décide

Figure 5

En définissant maxConcurrentOperationCount = 2, nous avons créé une file d’attente concurrente et les tâches s’exécutent maintenant simultanément, comme le montre la figure 6

Figure 6

Dépendances d’opérations

Comme le montre la figure 7, nous avons de nouveau créé une file d’attente série en ajoutant des dépendances entre deux tâches. Nous avons créé deux opérations de bloc et nous disons que ne démarrez pas la tâche 1 tant que la tâche 2 n’est pas terminée en appelant blockOperations1.addDependency(blockOperations2)

Figure 7

Implémentation du groupe de répartition À l’aide de la file d’attente des opérations

Dans la partie 2, nous avons utilisé la fonctionnalité de groupe de répartition GCD pour bloquer un thread jusqu’à ce qu’une ou plusieurs tâches aient terminé leur exécution. Comme le montre la figure 8, nous avons implémenté le même comportement en utilisant des files d’attente d’opérations en utilisant des dépendances. Ceci est très utile si vous ne pouvez pas progresser tant que toutes les tâches spécifiées ne sont pas terminées.

Comme le montre la figure 8, nous avons trois tâches et nous voulions les exécuter simultanément et lorsque toutes les tâches sont terminées, nous devons appeler une méthode pour indiquer que toutes les tâches sont terminées et ce que nous avons fait

  1. Créé une file d’attente d’opérations
  2. Créé trois opérations de bloc qui exécuteront des tâches
  3. Créé une opération de bloc d’achèvement (blockOperations4) qui se déclenchera lorsque les trois tâches seront terminées
  4. Fait blockOperations4 dépendant de blockOperations1, blockOperations2 et blockOperations3, ce qui signifie que blockOperations4 s’exécutera lorsque les trois tâches seront terminées
  5. waitUntilFinished → Bloque l’exécution du thread actuel jusqu’à ce que l’objet operation termine sa tâche puisque nous ne voulons pas bloquer le thread actuel qui est principal, nous l’affectons avec false
  6. Exécutez ce code et « Toutes les opérations sont terminées » s’affichera lorsque les tâches 1, 2 et 3 seront terminées

Figure 8

Comme le montre la figure 9, nous bloquons simplement le thread principal en définissant waitUntilFinished = true. , donc la question est de savoir quand cela est utile et vous obtiendrez la réponse dans la section suivante

Figure 9

Comme le montre la figure 10, nous avons implémenté un comportement de groupe de répartition en utilisant la file d’attente d’opérations sans utiliser de dépendances ce que nous avons fait, nous avons utilisé la fonctionnalité waitUntilFinished de manière appropriée. Si vous êtes sur un thread d’arrière-plan, vous pouvez bloquer ce thread pour obtenir ce comportement. Je suis intentionnellement passé au thread d’arrière-plan en utilisant la méthode DispatchQueue.global().async voir la partie 1 pour comprendre ce code

Nous avons dit à la file d’attente d’opérations d’exécuter les tâches 1, 2 et 3 sur la file d’attente d’opérations et de bloquer le thread actuel jusqu’à ce que ces tâches simultanées terminent leur exécution

Figure 10

Avantages des files d’attente d’opérations Sur GCD

  1. L’API d’opérations prend en charge les dépendances. Vous pouvez créer très facilement des dépendances complexes entre les tâches, mais dans GCD, vous pouvez y parvenir, mais vous devez faire beaucoup de travail.
  2. Les classes NSOperation et NSOperationQueue ont un certain nombre de propriétés qui peuvent être observées, en utilisant KVO (Key Value Observing). C’est un autre avantage important si vous souhaitez surveiller l’état d’une opération ou d’une file d’attente d’opérations.
  3. Les opérations peuvent être interrompues, reprises et annulées. Une fois que vous expédiez une tâche à l’aide de Grand Central Dispatch, vous n’avez plus de contrôle ni de vision sur l’exécution de cette tâche. L’API NSOperation est plus flexible à cet égard, donnant au développeur le contrôle du cycle de vie de l’opération
  4. Le NSOperationQueue ajoute également un certain nombre d’avantages au mix. Par exemple, vous pouvez spécifier le nombre maximal d’opérations en file d’attente pouvant s’exécuter simultanément. Cela facilite le contrôle du nombre d’opérations exécutées en même temps ou la création d’une file d’attente d’opérations série.

À venir

Dans la partie suivante, nous examinerons le cas d’utilisation réel de la création d’une opération personnalisée

Liens utiles

· https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW1

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.