objective c - tutorial - ¿Por qué esta llamada dispatch_sync() se congela?
nsoperationqueue swift 3 example (2)
dispatch_get_current_queue()
está en desuso a partir de iOS 6, y dispatch_get_current_queue() == dispatch_get_main_queue()
resultó ser false
mientras estaba en el hilo principal en iOS 6.1.3.
En iOS 6 y más allá simplemente hazlo:
dispatch_block_t block = ^
{
<your code here>
};
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
Estoy usando el marco de prueba de Kiwi para probar un método de autenticación en mi aplicación. La prueba se congela en una llamada a dispatch_sync que se ve así:
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_sync(main, ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
});
Me gustaría saber por qué se congela allí, si alguien tiene alguna pista.
Para la segunda parte de su pregunta con respecto a la pista sobre la congelación:
Cuando llame a dispatch_sync
en una cola, siempre verifique que esta cola no sea ya la actual ( dispatch_get_current_queue()
). Debido a que dispatch_sync
pondrá en cola su bloque en la cola pasada como el primer parámetro, y luego esperará a que se ejecute este bloque antes de continuar .
Entonces, si el dispatch_get_current_queue()
y la cola en la que encola su bloque son iguales, es decir, la cola principal en su caso, la cola principal bloqueará la llamada a dispatch_sync hasta que ... la cola principal ejecute el bloque, pero puede ''t, como la cola está bloqueada, y tiene un hermoso punto muerto aquí .
Una solución ([EDIT] hasta iOS6):
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_block_t block = ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
};
if (dispatch_get_current_queue() == main)
block(); // execute the block directly, as main is already the current active queue
else
dispatch_sync(main, block); // ask the main queue, which is not the current queue, to execute the block, and wait for it to be executed before continuing
[EDITAR] Tenga cuidado, dispatch_get_current_queue()
solo debe usarse para depuración y nunca en producción. De hecho, dispatch_get_current_queue
está en desuso desde iOS6.1.3.
Si está en el caso específico de la cola principal (que está asociada solo con el hilo principal), puede probar [NSThread isMainThread]
como lo sugiere @ meaning-matters.
Por cierto, ¿está seguro de que necesita dispatch_sync
en su caso? Supongo que enviar su notificación un poco más tarde, evitando bloquear hasta que se haya enviado, es aceptable en su caso, por lo que también puede considerar el uso de dispatch_async
(en lugar de usar dispatch_sync
y necesita la condición de comparación de cola), lo que evitaría el problema del interbloqueo también.