web-dev-qa-db-fra.com

iPhone - Fil principal de Grand Central Dispatch

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.

145
SpaceDog

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.

  • traitement en arrière-plan terminé -> mise à jour de l'interface utilisateur
  • bloc de données traité dans la file d'attente en arrière-plan -> signalez la file d'attente principale pour démarrer le bloc suivant
  • données réseau entrantes dans la file d'attente en arrière-plan -> signalez à la file d'attente principale que le message est arrivé
  • etc

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.

293
Robin Summerhill

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.

15
bames53

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

11
timthetoolman

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.

8
weaselfloss1

Swift 3, 4 & 5

Exécuter du code sur le thread principal

DispatchQueue.main.async {
    // Your code here
}
8
Niall Kiddle

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

1
Esqarrouth