iphone - ¿Qué sucederá si tengo llamadas dispatch_async anidadas?
ios objective-c (1)
Puede ser una pregunta tonta, pero necesito preguntar y aclarar esto por mí mismo.
Para enviar un bloque a una cola para su ejecución, use las funciones dispatch_sync
y dispatch_async
. Ambos toman una cola y un bloque como parámetros. dispatch_async
regresa de inmediato, ejecutando el bloque de forma asincrónica, mientras que dispatch_sync
bloquea la ejecución hasta que el bloque proporcionado retorna. Aquí hay algunas situaciones:
Situación 1
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_async(queue, ^{
NSLog(@"this is statement1");
});
});
Situacion 2
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_sync(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_sync(queue, ^{
NSLog(@"this is statement1");
});
});
Situacion 3
{
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_sync(queue, ^{
NSLog(@"this is statement1");
});
});
Situación 4
{
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_sync(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_async(queue, ^{
NSLog(@"this is statement1");
});
});
}
Y goDoSomethingLongAndInvolved
es
-(void)goDoSomethingLongAndInvolved {
NSLog(@"goDoSomethingLongAndInvolved");
}
Intenté ejecutarlos en Xcode pero no puedo ver la diferencia.
Así que mis preguntas son:
- ¿Cuál es la principal diferencia entre estas situaciones?
- ¿Qué pasa si reemplazo la
queue
condispatch_get_main_queue()
?
La instrucción dispatch_sync
espera hasta que el bloque que cubre se ejecute por completo. dispatch_async
regresa inmediatamente y pasa a la siguiente línea de código, por lo que todo lo que está sucediendo sucede en paralelo.
Si la queue
era una cola en serie creada por usted mismo, entonces:
Situación 1 - El bloque raíz regresa inmediatamente. En el interior espera por [self go ....], y luego va a dispatch_async, que también regresa de inmediato.
Situación 2 - Si la queue
fuera una cola en serie, entonces habría un bloqueo muerto ya que esperará a que termine de ejecutarse. Como se trata de uno asíncrono, ese bloque se ejecutará en paralelo. (Gracias, @Ken Thomases)
Situación 3 - No hay necesidad en dispatch_sync
aquí. Causa el punto muerto.
Situación 4 - Espera a [auto ...], luego regresa inmediatamente.
Si reemplaza la queue
con la queue
principal, recuerde no dispatch_sync
en la cola principal, ya que causará un interbloqueo (no se enviará desde el hilo principal, gracias a @Ken Thomases).
Para entenderlo mejor, reemplaza tu función con:
-(void)goDoSomethingLongAndInvolved:(NSString *)message {
for(int i = 0; i < 50; ++i) {
NSLog(@"%@ -> %d", message, i);
}
}
Verás claramente lo que está sucediendo cada vez, ya sea que espere o no. Buena suerte.