iOS
Concurrencia
Buscar..
Introducción
Tema relacionado: Grand Central Dispatch
Sintaxis
- dispatch_async: ejecuta un bloque de código en una cola separada y no detiene la cola actual. Si la cola está en un hilo diferente al que se llamó dispatch_async, el código en el bloque se ejecutará mientras que el código después de que dispatch_async también se ejecute
- dispatch_sync - Se ejecuta un bloque de código en una cola separada, y se detiene la cola actual. Si la cola está en un subproceso diferente al que se llamó dispatch_async, el código en el bloque se ejecutará, y la ejecución en el subproceso donde se llamó el método solo se reanudará después de que finalice
Parámetros
cola | La cola en la que se ejecutará el código en el bloque de envío. Una cola es como (pero no exactamente igual que) un hilo; El código en diferentes colas puede ejecutarse en paralelo. Use dispatch_get_main_queue para obtener la cola para el hilo principal Para crear una nueva cola, que a su vez crea un nuevo hilo, use dispatch_queue_create("QUEUE_NAME", DISPATCH_QUEUE_CONCURRENT) . El primer parámetro es el nombre de la cola, que se muestra en el depurador si hace una pausa mientras el bloque todavía se está ejecutando. El segundo parámetro no importa a menos que desee utilizar la misma cola para múltiples llamadas dispatch_async o dispatch_sync . Describe lo que sucede cuando otro bloque se coloca en la misma cola; DISPATCH_QUEUE_CONCURRENT hará que ambos bloques se ejecuten al mismo tiempo, mientras que DISPATCH_QUEUE_SERIAL hará que el segundo bloque espere a que finalice el primer bloque. |
---|---|
bloquear | El código en este bloque se ejecutará en la cola de queue ; ponga el código que desea ejecutar en la cola separada aquí. Un consejo útil: si está escribiendo esto en Xcode y el argumento del bloque tiene el contorno azul a su alrededor, haga doble clic en el argumento y Xcode creará automáticamente un bloque vacío (esto se aplica a todos los argumentos del bloque en cualquier función o método) |
Observaciones
Siempre que haga algo en un subproceso separado, lo que ocurre cuando se usan colas, es importante mantener la seguridad de los subprocesos. Es posible que algunos métodos, en particular los de UIView
s, no funcionen y / o se bloqueen en hilos distintos al hilo principal. Además, asegúrese de no cambiar nada (variables, propiedades, etc.) que también se esté utilizando en el hilo principal, a menos que tenga en cuenta este cambio.
Ejecutar código simultáneamente: ejecutar código mientras se ejecuta otro código
Digamos que quieres actuar en acción (en este caso, registrar "Foo"), mientras haces otra cosa (registrar "Barra"). Normalmente, si no usa la concurrencia, una de estas acciones se ejecutará completamente, y la otra ejecución se ejecutará solo después de que haya finalizado por completo. Pero con la concurrencia, puede hacer que ambas acciones se ejecuten al mismo tiempo:
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);
}
Esto registrará "Foo" 100 veces, haciendo una pausa de 100 ms cada vez que se registre, pero hará todo esto en un hilo separado. Mientras se está registrando Foo
, "Barra" también se registrará en intervalos de 50 ms, al mismo tiempo. Idealmente debería ver una salida con "Foo" y "Barras" mezcladas
Ejecutando en el hilo principal
Cuando se realizan tareas de forma asíncrona, normalmente se convierte en una necesidad de garantizar que se ejecute un fragmento de código en el hilo principal. Por ejemplo, puede querer golpear una API REST de forma asíncrona, pero poner el resultado en una UILabel en la pantalla. Antes de actualizar UILabel, debe asegurarse de que su código se ejecute en el hilo principal:
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 = //....
});
}
Siempre que actualice las vistas en la pantalla, asegúrese de hacerlo en el hilo principal, de lo contrario podría ocurrir un comportamiento indefinido.
Grupo de despacho - esperando otros hilos completados.
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");
});
Actualización 1. Swift 3 versión.
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")
}