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?
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
et vous voyez toujours 12
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.
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
}