Ricerca…
introduzione
Argomento correlato: Grand Central Dispatch
Sintassi
- dispatch_async: esegue un blocco di codice in una coda separata e non interrompe la coda corrente. Se la coda è su un thread diverso da quello su cui è stato chiamato dispatch_async, il codice nel blocco verrà eseguito mentre il codice dopo l'esecuzione di dispatch_async
- dispatch_sync - Esegue un blocco di codice in una coda separata, e si ferma la coda corrente. Se la coda è su un thread diverso da quello su cui è stato chiamato dispatch_async, verrà eseguito il codice nel blocco e l'esecuzione sul thread in cui è stato chiamato il metodo riprenderà solo dopo il completamento
Parametri
coda | La coda in cui verrà eseguito il codice nel blocco di invio. Una coda è simile (ma non esattamente uguale a) a un thread; il codice in code diverse può essere eseguito in parallelo. Usa dispatch_get_main_queue per ottenere la coda per il thread principale Per creare una nuova coda, che a sua volta crea un nuovo thread, usa dispatch_queue_create("QUEUE_NAME", DISPATCH_QUEUE_CONCURRENT) . Il primo parametro è il nome della coda, che viene visualizzato nel debugger se si mette in pausa mentre il blocco è ancora in esecuzione. Il secondo parametro non ha importanza se non si desidera utilizzare la stessa coda per più chiamate dispatch_async o dispatch_sync . Descrive cosa succede quando un altro blocco viene inserito nella stessa coda; DISPATCH_QUEUE_CONCURRENT farà sì che entrambi i blocchi vengano eseguiti allo stesso tempo, mentre DISPATCH_QUEUE_SERIAL farà in modo che il secondo blocco attenda che il primo blocco finisca |
---|---|
bloccare | Il codice in questo blocco verrà eseguito nella coda della queue ; inserisci il codice che vuoi eseguire sulla coda separata qui. Un consiglio utile: se stai scrivendo questo in Xcode e l'argomento del blocco ha il contorno blu attorno ad esso, fai doppio clic sull'argomento e Xcode creerà automaticamente un blocco vuoto (questo vale per tutti gli argomenti dei blocchi in qualsiasi funzione o metodo) |
Osservazioni
Ogni volta che fai qualcosa su un thread separato, cosa che succede quando usi le code, è importante mantenere la sicurezza dei thread. Alcuni metodi, in particolare quelli per UIView
, potrebbero non funzionare e / o bloccarsi su thread diversi dal thread principale. Inoltre, assicurati di non modificare nulla (variabili, proprietà, ecc.) Che viene utilizzato anche sul thread principale, a meno che tu non stia tenendo conto di questo cambiamento
Esecuzione simultanea del codice: esecuzione di codice durante l'esecuzione di altro codice
Dite che vuoi eseguire in azione (in questo caso, registrando "Foo"), mentre fai qualcos'altro (registrando "Bar"). Normalmente, se non si utilizza la concorrenza, una di queste azioni sarà completamente eseguita e l'altra esecuzione verrà eseguita solo dopo che è stata completata. Ma con la concorrenza, puoi eseguire entrambe le azioni contemporaneamente:
dispatch_async(dispatch_queue_create("Foo", DISPATCH_QUEUE_CONCURRENT), ^{
for (int i = 0; i < 100; i++) {
NSLog(@"Foo");
usleep(100000);
}
});
for (int i = 0; i < 100; i++) {
NSLog(@"Bar");
usleep(50000);
}
Questo registrerà "Foo" 100 volte, fermandosi per 100ms ogni volta che registra, ma farà tutto questo su un thread separato. Mentre viene registrato Foo
, "Bar" verrà anche registrato a intervalli di 50 ms, allo stesso tempo. Dovresti idealmente vedere un output con "Foo" e "Bars" mescolati insieme
Esecuzione sul thread principale
Quando si eseguono attività in modo asincrono, in genere diventa necessario assicurarsi che una parte di codice venga eseguita sul thread principale. Ad esempio potresti voler colpire un'API REST in modo asincrono, ma inserire il risultato in una UILabel sullo schermo. Prima di aggiornare UILabel devi assicurarti che il tuo codice sia eseguito sul thread principale:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Perform expensive tasks
//...
//Now before updating the UI, ensure we are back on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
label.text = //....
});
}
Ogni volta che aggiorni le visualizzazioni sullo schermo, assicurati sempre di farlo sul thread principale, altrimenti potrebbe verificarsi un comportamento non definito.
Gruppo di spedizione - in attesa di altri thread completati.
dispatch_group_t preapreWaitingGroup = dispatch_group_create();
dispatch_group_enter(preapreWaitingGroup);
[self doAsynchronousTaskWithComplete:^(id someResults, NSError *error) {
// Notify that this task has been completed.
dispatch_group_leave(preapreWaitingGroup);
}]
dispatch_group_enter(preapreWaitingGroup);
[self doOtherAsynchronousTaskWithComplete:^(id someResults, NSError *error) {
dispatch_group_leave(preapreWaitingGroup);
}]
dispatch_group_notify(preapreWaitingGroup, dispatch_get_main_queue(), ^{
// This block will be executed once all above threads completed and call dispatch_group_leave
NSLog(@"Prepare completed. I'm readyyyy");
});
Aggiornamento 1. Versione Swift 3.
let prepareGroup = DispatchGroup()
prepareGroup.enter()
doAsynchronousTaskWithComplete() { (someResults, error) in
// Notify that this task has been completed.
prepareGroup.leave()
}
prepareGroup.enter()
doOtherAsynchronousTaskWithComplete() { (someResults, error) in
// Notify that this task has been completed.
prepareGroup.leave()
}
prepareGroup.notify(queue: DispatchQueue.main) {
// This block will be executed once all above threads completed and call dispatch_group_leave
print("Prepare completed. I'm readyyyy")
}