ios - dispatch_sync siempre programando un bloque en Main Thread
objective-c cocoa-touch (4)
Aquí es cómo puedes hacer esto en Swift:
runThisInMainThread { () -> Void in
// Runs in the main thread
}
func runThisInMainThread(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
Está incluido como una función estándar en mi repositorio, échale un vistazo: https://github.com/goktugyil/EZSwiftExtensions
Estoy ejecutando un bloque usando dispatch_sync y el bloque se ejecuta correctamente. Pero este bloque se ejecuta en el hilo principal. Según el Apple Doc:
Las colas en serie (también conocidas como colas de envío privadas) ejecutan una tarea a la vez en el orden en que se agregan a la cola. La tarea que se está ejecutando actualmente se ejecuta en un hilo distinto (que puede variar de una tarea a otra) que es administrado por la cola de envío.
lo que significa (o lo que yo entendí) que el proceso actual que se está ejecutando se ejecutará en un hilo separado.
A continuación se muestra el código que estoy usando para juzgar lo que está sucediendo. Se está llamando dentro del método didReceiveData de NSURLConnection: delegar método (sé que no debería hacer eso dentro del método delegarDataData: delegar, pero esto es solo una muestra para centrarse en dispatch_sync). Las siguientes son las diferentes maneras en que puedo asumir como una prueba de mi conclusión:
Utilizando dispatch_sync en una Cola concurrente global
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if ([NSThread isMainThread]) { NSLog(@"Main Thread"); } else NSLog(@"Not on Main Thread"); //Some Process });
Salida -
Main Thread
Main Thread
Main Thread
// Main Thread printed till didReceiveData: gets called
Usar dispatch_sync en una cola creada por uno mismo utilizando dispatch_queue_create
// Create queue somewhere else like this dispatch_queue_t newQueue = dispatch_queue_create("WriteQueue", DISPATCH_QUEUE_SERIAL); dispatch_sync(newQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"Main Thread"); } else NSLog(@"Not on Main Thread"); //Some Process });
Salida -
Main Thread
Main Thread
Main Thread
// Main Thread printed till didReceiveData: gets called
Estoy un poco sorprendido aquí, el bloqueo se ejecuta siempre en el hilo principal o me falta algo. Porque parece ir en contra del Apple Doc, creo que sí. ¿Alguien sabe de qué se trata todo esto?
Actualización : según otras discusiones, entiendo que dispatch_sync ejecuta un bloque en el mismo hilo (la mayoría de las veces), entonces, por qué las declaraciones de Apple Doc contradicen de alguna manera. ¿Por qué dice Apple? " La tarea que se está ejecutando actualmente se ejecuta en un hilo distinto (que puede variar de una tarea a otra) que es administrado por la cola de despacho ". ¿O aún me falta algo?
Es importante darse cuenta de que Grand Central Dispatch puede garantizar que un bloque enviado a la cola principal se ejecutará en el hilo principal, pero un bloque enviado a cualquier otra cola no tiene garantías sobre qué hilo ejecutará un bloque.
No se garantiza el hilo con el que se invocará un bloque; sin embargo, se garantiza que solo se invocará un bloque enviado a la cola de despacho FIFO a la vez.
Grand Central Dispatch administra un grupo de hilos y reutiliza los hilos existentes tanto como sea posible. Si el hilo principal está disponible para el trabajo (es decir, inactivo), se puede ejecutar un bloque en ese hilo.
Para un bloque de fondo, use
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// background code
});
Tenga en cuenta que es _async y no _sync
EDITAR: Del mismo modo, para ejecutar algo en el hilo principal, use
dispatch_async(dispatch_get_main_queue(), ^{
// main thread code
});
dispatch_sync () distribuye el bloque en el mismo hilo, eso es normal.
EDITAR
La Documentación de Apple no solo dice esto, también dice esto:
Como optimización, esta función invoca el bloque en el hilo actual cuando sea posible.
Como nota al margen (sé que estás hablando de la versión síncrona, pero vamos a especificar esto) diría que también dispatch_async () puede causar que se ejecuten varios bloques en el mismo hilo.