web-dev-qa-db-fra.com

OperationQueue.main vs DispatchQueue.main

Lorsque vous devez effectuer quelque chose sur le thread principal dans le bloc d'achèvement d'une tâche de mise en réseau ou d'une opération, laquelle de ces méthodes serait la plus appropriée et pourquoi?:

  • OperationQueue.main.addOperation
  • DispatchQueue.main.async
22
AppsDev

Pour plus de détails sur les différences entre les deux types de file d'attente, voir la réponse de Lion.

Les deux approches fonctionneront. Cependant, NSOperation est surtout nécessaire lorsqu'une planification plus avancée (y compris dépendances, annulation, etc.) est requise. Donc, dans ce cas, un simple

DispatchQueue.main.async { /* do work */ }

sera très bien. Ce serait équivalent à

dispatch_async(dispatch_get_main_queue(), ^{ /* do work */ });

dans Objective-C, qui est aussi la façon dont je le ferais dans ce langage.

13
MrMage

Quand utiliser NSOperation

L'API NSOperation est idéale pour encapsuler des blocs de fonctionnalités bien définis. Vous pouvez, par exemple, utiliser une sous-classe NSOperation pour encapsuler la séquence de connexion d'une application.

La gestion de la dépendance est la cerise sur le gâteau. Une opération peut avoir des dépendances avec d'autres opérations et c'est une fonctionnalité puissante qui manque à Grand Central Dispatch. Si vous devez effectuer plusieurs tâches dans un ordre spécifique, les opérations sont une bonne solution.

Vous pouvez aller trop loin avec les opérations si vous créez des dizaines d'opérations dans un court laps de temps. Cela peut entraîner des problèmes de performances en raison de la surcharge inhérente à NSOperation API.

Quand utiliser Grand Central Dispatch

Grand Central Dispatch est idéal si vous avez juste besoin d'envoyer un bloc de code dans une file d'attente série ou simultanée.

Si vous ne voulez pas passer par les tracas de la création d'un NSOperation subclass pour une tâche banale, puis Grand Central Dispatch est une excellente alternative. Un autre avantage de Grand Central Dispatch est que vous pouvez conserver le code associé ensemble. Jetez un œil à l'exemple suivant.

let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Process Response
...

dispatch_async(dispatch_get_main_queue(), { () -> Void in
    // Update User Interface
    ...
})
})

Dans le gestionnaire d'achèvement de la tâche de données, nous traitons la réponse et mettons à jour l'interface utilisateur en envoyant une fermeture (ou un bloc) à la file d'attente principale. Cela est nécessaire car nous ne savons pas sur quel thread le gestionnaire d'achèvement est exécuté et il s'agit très probablement d'un thread d'arrière-plan.

Cité textuellement par cette source

10
Pooja Srivastava

DispatchQueue gère l'exécution des éléments de travail. Chaque élément de travail soumis à une file d'attente est traité sur un pool de threads géré par le système.

Référence: Apple Doc

La classe NSOperationQueue régule l'exécution d'un ensemble d'objets Operation. Après avoir été ajoutée à une file d'attente, une opération reste dans cette file d'attente jusqu'à ce qu'elle soit explicitement annulée ou finisse d'exécuter sa tâche. Les opérations dans la file d'attente (mais pas encore en cours d'exécution) sont elles-mêmes organisées en fonction des niveaux de priorité et des dépendances des objets inter-opérations et sont exécutées en conséquence. Une application peut créer plusieurs files d'attente d'opérations et soumettre des opérations à l'une d'entre elles.

Référence: Apple Doc

Donc, vous devriez préférer DispatchQueue.main.async lorsque vous souhaitez effectuer quelque chose sur le thread principal à partir du bloc d'achèvement d'un appel réseau. Surtout quand elle est liée à UI Updates! Et si votre tâche est complexe, je veux dire que si vous avez besoin d'opérations supplémentaires sur la tâche en cours d'exécution, vous pouvez utiliser OperationQueue.main.addOperation autrement DispatchQueue.main.async donnera des performances plus optimales comparativement!

9
Lion