iPhone: hilo principal de Grand Central Dispatch
Frecuentes
Visto 145,074 equipos
146
He estado usando con éxito, grand central dispatch en mis aplicaciones, pero me preguntaba cuál es la ventaja real 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á 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 sobre cuándo se ejecutará el bloque. He visto casos de bloques que se ejecutan medio segundo después de que los disparas. El segundo caso, es similar a
[self doStuff];
¿derecho?
Me pregunto qué piensan ustedes.
6 Respuestas
296
El envío de un bloque a la cola principal generalmente se realiza desde una cola en segundo plano para indicar que algún procesamiento en segundo plano ha finalizado, 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 = <some really long calculation that takes seconds to complete>;
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 interfaz de usuario cuando se complete el cálculo. La actualización de la interfaz de usuario normalmente se debe realizar desde la cola principal, por lo que 'señalizamos' de regreso a la cola principal utilizando un segundo dispatch_async anidado.
Probablemente hay otros ejemplos en los que es posible que desee enviar de nuevo a la cola principal, pero generalmente se hace de esta manera, es decir, anidado desde dentro de un bloque enviado a una cola en segundo plano.
- procesamiento en segundo plano terminado -> actualizar la interfaz de usuario
- fragmento de datos procesados en la cola en segundo plano -> señal de la cola principal para iniciar el siguiente fragmento
- datos de red entrantes en la cola de fondo -> señal de la cola principal que el mensaje ha llegado
- etc etc
En cuanto a por qué es posible que desee enviar a la cola principal del la cola principal ... Bueno, generalmente no lo haría, aunque es posible que lo haga para programar algo de trabajo para hacer la próxima vez en el ciclo de ejecución.
Respondido 21 Feb 13, 12:02
Ah, ya veo. Entonces, tengo razón. No hay ninguna ventaja en hacer eso si ya está en la cola principal, solo si está en otra cola y desea actualizar la interfaz de usuario. Gracias. - Duck
Acabo de editar mi respuesta para hablar sobre por qué no es muy útil hacer esto desde la cola principal. - petirrojo
Además, creo que hay un error en iOS 4 (podría haber ido en iOS 5), donde dispatch_sync a la cola principal desde el hilo principal solo causa un bloqueo, por lo que evitaría hacerlo por completo. - joerick
Eso no es un error, ese es el comportamiento esperado. Es cierto que no es un comportamiento muy útil, pero siempre debe estar al tanto de los interbloqueos al usar dispatch_sync. No puede esperar que el sistema lo proteja de los errores del programador todo el tiempo. - petirrojo
¿Qué es backgroundQueue aquí? ¿Cómo creo un objeto backgroundQueue? nilesh tupe
17
Envío de bloques a la cola principal desde el hilo principal podemos sé útil. Le da a la cola principal la oportunidad de manejar otros bloques que se han puesto en cola para que no esté simplemente bloqueando la ejecución de todo lo demás.
Por ejemplo, podría escribir un servidor esencialmente de un solo subproceso que, no obstante, maneje muchas conexiones simultáneas. Siempre que ningún bloque individual en la cola tarde demasiado, el servidor seguirá respondiendo a las nuevas solicitudes.
Si su programa no hace nada más que pasar toda su vida respondiendo a los eventos, esto puede ser bastante natural. Simplemente configure sus controladores de eventos para que se ejecuten en la cola principal y luego llame a dispatch_main (), y es posible que no tenga que preocuparse por la seguridad de los subprocesos en absoluto.
contestado el 28 de mayo de 15 a las 22:05
11
Espero haber entendido correctamente su pregunta, ya que se está preguntando acerca de las diferencias entre dispatch_async y dispatch_sync.
dispatch_async
enviará el bloque a una cola de forma asincrónica. Lo que significa que enviará el bloque a la cola y no esperará a que regrese 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á que se ejecute más el código restante en el método hasta que el bloque haya terminado de ejecutarse.
Mayormente he usado un dispatch_async
a una cola en segundo plano para sacar trabajo de la cola principal y aprovechar los núcleos adicionales que pueda tener el dispositivo. Luego dispatch_async
al hilo principal si necesito actualizar la interfaz de usuario.
Buena suerte
Respondido 18 Oct 13, 16:10
gracias, pero estoy preguntando acerca de las ventajas de enviar algo a la cola principal, estar en la cola principal. - Duck
9
Un lugar donde es útil es para las actividades de la interfaz de usuario, como configurar una ruleta antes de una operación prolongada:
- (void) handleDoSomethingButton{
[mySpinner startAnimating];
(do something lengthy)
[mySpinner stopAnimating];
}
no funcionará, porque está bloqueando el hilo principal durante su trabajo prolongado y no permitiendo que UIKit realmente inicie la ruleta.
- (void) handleDoSomethingButton{
[mySpinner startAnimating];
dispatch_async (dispatch_get_main_queue(), ^{
(do something lengthy)
[mySpinner stopAnimating];
});
}
devolverá el control al ciclo de ejecución, que programará la actualización de la interfaz de usuario, iniciará la ruleta y luego sacará lo siguiente de la cola de despacho, que es su procesamiento real. Cuando finaliza el procesamiento, se llama a la parada de la animación y regresa al bucle de ejecución, donde la interfaz de usuario se actualiza con la parada.
respondido 13 mar '15, 23:03
@Jerceratops sí, pero permite que se complete el ciclo de ejecución actual. - dan rosenstark
Sí, pero sigue siendo terrible. Todavía bloquea la interfaz de usuario. Podría presionar otro botón justo después de este. O intente desplazarse. "(hacer algo largo)" no debería suceder en el hilo principal, y dispatch_async para permitir que el botón haga clic en "finalizar" no es una solución aceptable. - Jerceratops
8
Swift 3, 4 y 5
Ejecutando código en el hilo principal
DispatchQueue.main.async {
// Your code here
}
Respondido 12 Abr '19, 12:04
1
Async significa asincrónico y debería usarlo la mayor parte del tiempo. Nunca debe llamar a la sincronización en el hilo principal porque bloqueará su interfaz de usuario hasta que se complete la tarea. Aquí hay 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 repositorio, compruébalo: https://github.com/goktugyil/EZSwiftExtensions
Respondido el 06 de diciembre de 15 a las 03:12
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas ios concurrency grand-central-dispatch dispatch-async or haz tu propia pregunta.
Por cierto, lanzar una cola principal en un dispatch_sync resultará en un punto muerto. - Brooks Hanes
Solo léelo en los documentos: "A diferencia de dispatch_async, [dispatch_sync] no regresa hasta que el bloque ha terminado. Llamar a esta función y apuntar a la cola actual da como resultado un punto muerto." ... Pero tal vez estoy leyendo esto mal ... ( la cola actual no significa hilo principal). Por favor corrija si me equivoco. - Brooks Hanes
@BrooksHanes no siempre es cierto. Resultará en un punto muerto if ya estás en el hilo principal. Si no, no habría un punto muerto. Ver aquí - Honey