iPhone – Tema principal de Grand Central Dispatch

He estado utilizando con éxito el gran despacho central en mis aplicaciones, pero me preguntaba cuál es la verdadera ventaja de usar algo como esto:

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff 

o incluso

 dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff 

Quiero decir, en ambos casos estás disparando un bloque para que se ejecute en el hilo principal, exactamente donde se ejecuta la aplicación y esto no ayudará a reducir la carga. En el primer caso, no tienes ningún control cuando se ejecutará el bloque. He visto casos de bloques que se ejecutan medio segundo después de dispararlos. El segundo caso, es similar a

 [self doStuff]; 

¿derecho?

Me pregunto qué piensan ustedes.

El envío de un bloque a la cola principal normalmente se realiza desde una cola de fondo para indicar que ha finalizado algún procesamiento de fondo, por ejemplo

 - (void)doCalculation { //you can use any string instead "com.mycompany.myqueue" dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0); dispatch_async(backgroundQueue, ^{ int result = ; dispatch_async(dispatch_get_main_queue(), ^{ [self updateMyUIWithResult:result]; }); }); } 

En este caso, estamos haciendo un cálculo extenso en una cola en segundo plano y necesitamos actualizar nuestra UI cuando el cálculo esté completo. Por lo general, la actualización de la IU debe hacerse desde la cola principal, por lo que ‘señalizamos’ de nuevo a la cola principal utilizando un segundo dispatch_async nested.

Probablemente existan otros ejemplos en los que desee enviar de vuelta a la cola principal, pero generalmente se hace de esta manera, es decir, nested desde dentro de un bloque enviado a una cola de fondo.

  • procesamiento de fondo finalizado -> actualizar la interfaz de usuario
  • fragmento de datos procesados ​​en cola de fondo -> cola principal de señal para comenzar el siguiente fragmento
  • datos de la red entrante en la cola de fondo -> cola principal de la señal que ha llegado el mensaje
  • etcétera etcétera

En cuanto a por qué es posible que desee enviar a la cola principal de la cola principal … Bueno, en general, aunque no concebiblemente, podría hacerlo para progtwigr algún trabajo para hacer la próxima vez en el ciclo de ejecución.

El envío de bloques a la cola principal desde el hilo principal puede ser útil. Le da a la cola principal la posibilidad de manejar otros bloques que se han puesto en cola para que no solo bloquee la ejecución de todo lo demás.

Por ejemplo, podría escribir un servidor con un único hilo que, sin embargo, maneja muchas conexiones simultáneas. Siempre que ningún bloque individual en la cola lleve demasiado tiempo, el servidor se mantiene receptivo a las nuevas solicitudes.

Si su progtwig no hace más que pasar toda su vida respondiendo a los eventos, entonces esto puede ser bastante natural. Simplemente configura los controladores de eventos para que se ejecuten en la cola principal y luego llames a dispatch_main (), y es posible que no tengas que preocuparte por la seguridad de los hilos.

Espero que entienda tu pregunta correctamente porque te preguntas acerca de las diferencias entre dispatch_async y dispatch_sync.

 dispatch_async 

enviará el bloque a una cola de forma asíncrona. Lo que significa que enviará el bloque a la cola y no esperará a que vuelva antes de continuar con la ejecución del código restante en su método.

 dispatch_sync 

enviará el bloque a una cola sincrónicamente. Esto evitará más ejecución del código restante en el método hasta que el bloque haya terminado de ejecutarse.

En su mayoría he usado un dispatch_async en una cola de segundo plano para obtener trabajo fuera de la cola principal y aprovechar cualquier núcleo adicional que pueda tener el dispositivo. Luego dispatch_async al hilo principal si necesito actualizar la interfaz de usuario.

Buena suerte

Un lugar donde es útil es para actividades de UI, como configurar un spinner antes de una operación prolongada:

 - (void) handleDoSomethingButton{ [mySpinner startAnimating]; (do something lengthy) [mySpinner stopAnimating]; } 

no funcionará, porque está bloqueando el hilo principal durante todo el proceso y no permite que UIKit realmente inicie el spinner.

 - (void) handleDoSomethingButton{ [mySpinner startAnimating]; dispatch_async (dispatch_get_main_queue(), ^{ (do something lengthy) [mySpinner stopAnimating]; }); } 

devolverá el control al bucle de ejecución, que progtwigrá la actualización de la IU, iniciará la ruleta y luego sacará lo siguiente de la cola de despacho, que es su procesamiento real. Cuando finaliza su procesamiento, se invoca la parada de animación y regresa al ciclo de ejecución, donde la interfaz de usuario se actualiza con la parada.

Swift 3 y 4

Ejecutando el código en el hilo principal

 DispatchQueue.main.async { // Your code here } 

Async significa asíncrono y deberías usarlo la mayor parte del tiempo. Nunca debe llamar a la sincronización en el hilo principal porque bloqueará su UI hasta que se complete la tarea. Usted aquí es una mejor manera de hacer esto en Swift:

 runThisInMainThread { () -> Void in // Run your code like this: self.doStuff() } func runThisInMainThread(block: dispatch_block_t) { dispatch_async(dispatch_get_main_queue(), block) } 

Está incluido como una función estándar en mi repository, échale un vistazo: https://github.com/goktugyil/EZSwiftExtensions