J'utilise avec succès, mon système de répartition centralisée dans mes applications, mais je me demandais quel était le véritable avantage d'utiliser un système comme celui-ci:
dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff
ou même
dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff
Je veux dire, dans les deux cas, vous activez un bloc à exécuter sur le thread principal, à l'endroit précis où l'application est exécutée, ce qui ne contribuera pas à réduire la charge. Dans le premier cas, vous n'avez aucun contrôle sur l'exécution du bloc. J'ai vu des cas de blocs être exécutés une demi-seconde après leur départ. Le deuxième cas, il est similaire à
[self doStuff];
droite?
Je me demande ce que vous en pensez.
La distribution d'un bloc dans la file d'attente principale est généralement effectuée à partir d'une file d'attente en arrière-plan pour signaler qu'un traitement en arrière-plan est terminé, par exemple.
- (void)doCalculation
{
//you can use any string instead "com.mycompany.myqueue"
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(backgroundQueue, ^{
int result = <some really long calculation that takes seconds to complete>;
dispatch_async(dispatch_get_main_queue(), ^{
[self updateMyUIWithResult:result];
});
});
}
Dans ce cas, nous effectuons un calcul long sur une file d'attente en arrière-plan et nous devons mettre à jour notre interface utilisateur une fois le calcul terminé. La mise à jour de l'interface utilisateur doit normalement être effectuée à partir de la file d'attente principale. Nous "signalons" ainsi à la file d'attente principale à l'aide d'un second dispatch_async imbriqué.
Il existe probablement d’autres exemples dans lesquels vous souhaiterez peut-être renvoyer dans la file d’attente principale, mais c’est généralement le cas de la manière suivante: imbriquée à partir d’un bloc distribué dans une file d’arrière-plan.
Pour ce qui est de la raison pour laquelle vous pourriez vouloir envoyer dans la file principale from la file principale ... Eh bien, vous ne le feriez généralement pas, mais vous pourriez le faire pour planifier du travail à faire la prochaine fois autour de la courir en boucle.
Envoi de blocs à la file principale à partir du thread principal can être utile. Cela donne à la file d'attente principale une chance de gérer d'autres blocs qui ont été mis en file d'attente afin que vous ne bloquiez pas simplement l'exécution de tout le reste.
Par exemple, vous pouvez écrire un serveur essentiellement à thread unique qui gère néanmoins de nombreuses connexions simultanées. Tant qu'aucun bloc individuel dans la file d'attente ne prend trop de temps, le serveur reste réactif aux nouvelles demandes.
Si votre programme ne fait rien d'autre que passer toute sa vie à réagir aux événements, cela peut être tout à fait naturel. Vous venez de configurer vos gestionnaires d'événements pour qu'ils s'exécutent dans la file principale, puis appelez dispatch_main (), sans que vous ayez à vous soucier de la sécurité des threads.
J'espère que je comprends bien votre question en ce sens que vous vous interrogez sur les différences entre dispatch_async et dispatch_sync?
dispatch_async
envoie le bloc dans une file d'attente de manière asynchrone. Cela signifie que le bloc sera envoyé à la file d'attente sans attendre son retour avant de poursuivre l'exécution du code restant dans votre méthode.
dispatch_sync
envoie le bloc dans une file d'attente de manière synchrone. Cela empêchera toute exécution ultérieure du code restant dans la méthode jusqu'à ce que l'exécution du bloc soit terminée.
J'ai principalement utilisé un dispatch_async
dans une file d'attente en arrière-plan pour travailler hors de la file principale et tirer parti des noyaux supplémentaires éventuellement présents sur le périphérique. Puis dispatch_async
au thread principal si je dois mettre à jour l'interface utilisateur.
Bonne chance
Un endroit où il est utile est pour les activités d'interface utilisateur, comme de placer une roulette avant une longue opération:
- (void) handleDoSomethingButton{
[mySpinner startAnimating];
(do something lengthy)
[mySpinner stopAnimating];
}
ne fonctionnera pas, parce que vous bloquez le fil principal pendant votre travail prolongé et que vous ne laissez pas UIKit démarrer le spinner.
- (void) handleDoSomethingButton{
[mySpinner startAnimating];
dispatch_async (dispatch_get_main_queue(), ^{
(do something lengthy)
[mySpinner stopAnimating];
});
}
retournera le contrôle à la boucle d’exécution, qui planifiera la mise à jour de l’interface utilisateur en commençant par le tourniquet, puis obtiendra le prochain élément de la file d’acheminement, qui est votre traitement réel. Lorsque votre traitement est terminé, l'animation stop est appelée et vous revenez à la boucle d'exécution, où l'interface utilisateur est ensuite mise à jour avec l'arrêt.
Swift 3, 4 & 5
Exécuter du code sur le thread principal
DispatchQueue.main.async {
// Your code here
}
Async signifie asynchrone et vous devriez l'utiliser la plupart du temps. Vous ne devez jamais appeler sync sur le thread principal, car il bloquera votre interface utilisateur jusqu'à ce que la tâche soit terminée. Vous voici une meilleure façon de faire cela dans Swift:
runThisInMainThread { () -> Void in
// Run your code like this:
self.doStuff()
}
func runThisInMainThread(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
Son inclus en tant que fonction standard dans mon référentiel, consultez-le: https://github.com/goktugyil/EZSwiftExtensions