serial grand gcd example dispatchqueue create central iphone objective-c multithreading ios grand-central-dispatch

iphone - grand - swift 4 dispatch main



Grand Central Dispatch(GCD) vs. performSelector-necesita una mejor explicación (3)

He usado tanto GCD como performSelectorOnMainThread: waitUntilDone en mis aplicaciones, y tiendo a pensar que son intercambiables, es decir, performSelectorOnMainThread: waitUntilDone es un envoltorio de Obj-C con la sintaxis de GCD C. He estado pensando en estos dos comandos como equivalentes:

dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; }); [self performSelectorOnMainThread:@selector(doit:) withObject:YES waitUntilDone:YES];

¿Soy incorrecto? Es decir, ¿hay alguna diferencia entre los comandos de performSelector * y los de GCD? He leído mucha documentación sobre ellos, pero todavía tengo que ver una respuesta definitiva.


Como señala Jacob, aunque puedan parecer lo mismo, son cosas diferentes. De hecho, hay una diferencia significativa en la forma en que manejan el envío de acciones al hilo principal si ya se está ejecutando en el hilo principal.

Me encontré con esto recientemente, donde tenía un método común que a veces se ejecutaba desde algo en el hilo principal, a veces no. Para proteger ciertas actualizaciones de UI, he estado usando -performSelectorOnMainThread: para ellos sin problemas.

Cuando cambié a usar dispatch_sync en la cola principal, la aplicación se estancaba cada vez que se ejecutaba este método en la cola principal. Al leer la documentación en dispatch_sync , vemos:

Llamar a esta función y apuntar a la cola actual resulta en un punto muerto.

donde para -performSelectorOnMainThread: vemos

Espere

Un booleano que especifica si el hilo actual se bloquea hasta después de que el selector especificado se realice en el receptor en el hilo principal. Especifique SÍ para bloquear este hilo; de lo contrario, especifique NO para que este método se devuelva inmediatamente.

Si el hilo actual también es el hilo principal y especifica SÍ para este parámetro, el mensaje se entrega y se procesa inmediatamente.

Todavía prefiero la elegancia de GCD, la mejor verificación en tiempo de compilación que proporciona, y su mayor flexibilidad en cuanto a argumentos, etc., así que hice esta pequeña función de ayudante para evitar interbloqueos:

void runOnMainQueueWithoutDeadlocking(void (^block)(void)) { if ([NSThread isMainThread]) { block(); } else { dispatch_sync(dispatch_get_main_queue(), block); } }

Actualización: en respuesta a Dave Dribin señalando la sección de advertencias en dispatch_get_current_queue() , he cambiado a usar [NSThread isMainThread] en el código anterior.

Entonces uso

runOnMainQueueWithoutDeadlocking(^{ //Do stuff });

para realizar las acciones que necesito asegurar en el hilo principal, sin preocuparme sobre en qué subproceso se ejecutó el método original.


Se supone que la forma de GCD es más eficiente y fácil de manejar, y solo está disponible en iOS4 en adelante, mientras que la función de rendimiento es compatible con el iOS anterior y posterior.


performSelectorOnMainThread: no utiliza GCD para enviar mensajes a objetos en el hilo principal.

Así es como la documentation dice que el método está implementado:

- (void) performSelectorOnMainThread:(SEL) selector withObject:(id) obj waitUntilDone:(BOOL) wait { [[NSRunLoop mainRunLoop] performSelector:selector target:self withObject:obj order:1 modes: NSRunLoopCommonModes]; }

Y en performSelector:target:withObject:order:modes: la documentación indica:

Este método configura un temporizador para realizar el mensaje aSelector en el ciclo de ejecución del subproceso actual al comienzo de la siguiente iteración del ciclo de ejecución. El temporizador está configurado para ejecutarse en los modos especificados por el parámetro de modos. Cuando el temporizador se dispara, el hilo intenta quitar la cola del mensaje del ciclo de ejecución y realizar el selector. Tiene éxito si el ciclo de ejecución se está ejecutando y en uno de los modos especificados; de lo contrario, el temporizador espera hasta que el ciclo de ejecución esté en uno de esos modos.