web-dev-qa-db-fra.com

Différence entre dispatch_async et dispatch_sync sur une file d'attente série?

J'ai créé une file d'attente série comme ceci:

    dispatch_queue_t _serialQueue = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);

Quelle est la différence entre dispatch_async appelé comme ça

 dispatch_async(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_async(_serialQueue, ^{ /* TASK 2 */ });

Et dispatch_sync appelé comme ça sur cette file d'attente?

 dispatch_sync(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_sync(_serialQueue, ^{ /* TASK 2 */ });

Je crois comprendre que, quelle que soit la méthode de répartition utilisée, TASK 1 sera exécuté et terminé avant le TASK 2, correct?

118
JRG-Developer

Oui. L'utilisation de la file d'attente série assure l'exécution en série des tâches. La seule différence est que dispatch_sync N'est renvoyé qu'après la fin du bloc, tandis que dispatch_async Est renvoyé après son ajout dans la file d'attente et peut ne pas être terminé.

pour ce code

dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");

Il peut imprimer 2413 Ou 2143 Ou 1234 Mais 1 Toujours avant 3

pour ce code

dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");

il affiche toujours 1234


Remarque: Pour le premier code, il ne sera pas print 1324. Parce que printf("3") est envoyé aprèsprintf("2") est exécuté. Et une tâche ne peut être exécutée que après elle est envoyée.


Le temps d'exécution des tâches ne change rien. Ce code affiche toujours 12

dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });

Ce qui peut arriver est

  • Thread 1: dispatch_async une tâche fastidieuse (tâche 1) vers une file d'attente série
  • Thread 2: commencer à exécuter la tâche 1
  • Thread 1: dispatch_async une autre tâche (tâche 2) dans la file d'attente série
  • Fil 2: la tâche 1 est terminée. commencer à exécuter la tâche 2
  • Fil 2: la tâche 2 est terminée.

et vous voyez toujours 12

399
Bryan Chen

La différence entre dispatch_sync et dispatch_async est simple.

Dans vos deux exemples, TASK 1 sera toujours exécuté avant TASK 2 parce qu'il a été expédié avant.

Dans le dispatch_sync exemple, cependant, vous n’envoyez pas TASK 2 jusqu'après TASK 1 a été envoyé et exécuté . Cela s'appelle "blocage" . Votre code attend (ou "bloque") jusqu'à l'exécution de la tâche.

Dans le dispatch_async _ exemple, votre code n'attendra pas que l'exécution soit terminée. Les deux blocs seront envoyés (et mis en file d'attente) dans la file d'attente et le reste de votre code continuera de s'exécuter sur ce thread. Ensuite, à un moment donné dans le futur ((en fonction de ce qui a été envoyé dans votre file d'attente), Task 1 s'exécutera puis Task 2 s'exécutera.

18
Dave DeLong

Tout est lié à la file d'attente principale. Il y a 4 permutations.

i) File d'attente série, asynchrone: Ici, les tâches s'exécuteront l'une après l'autre, mais le thread principal (effet sur l'interface utilisateur) n'attendra pas le retour.

ii) File d'attente série, synchronisation de dispatch: les tâches s'exécuteront l'une après l'autre, mais le thread principal (effet sur l'interface utilisateur) affichera un décalage

iii) File d'attente simultanée, dispatch async: Ici, les tâches seront exécutées en parallèle et le thread principal (effet sur l'interface utilisateur) n'attendra pas le retour et sera lisse.

iv) File d'attente simultanée, synchronisation de dispatch: Ici, les tâches seront exécutées en parallèle, mais le thread principal (effet sur l'interface utilisateur) affichera un décalage

Votre choix de file d'attente simultanée ou série dépend de si vous avez besoin d'une sortie d'une tâche précédente pour la suivante. Si vous dépendez de la tâche précédente, adoptez la file d'attente série, sinon prenez une file d'attente simultanée.

Enfin, c’est une façon de revenir au fil conducteur lorsque nous avons terminé notre activité:

DispatchQueue.main.async {
     // Do something here
}
3
rd_