2012-06-08 15 views
16

Podemos tener muchos controladores: controlador de toques, controlador UIControl (botones, controles deslizantes), performSelector, CADisplayLink, eventos NSTimer, Gesture Recognizer, controlador de acelerómetro y bloque de finalización de animación UIView, y algunos otros .¿Todos los métodos en una aplicación de iOS generalmente están en un único hilo? (para prevención de condición de carrera)

¿Están todos en el mismo hilo? Es decir, ¿solo uno de ellos puede estar funcionando al mismo tiempo?

¿Puede algún otro método o manejador ser parte de otro hilo y por lo tanto puede crear condiciones de carrera?

+1

+1 bonita pregunta –

Respuesta

16

En general, encontrará que las aplicaciones más simples en iOS tienden a realizar casi todas las acciones en el hilo principal. Tal como lo notó, en el instante en que incorpora el subprocesamiento múltiple a la imagen, agrega otra serie de cuestiones difíciles de las que debe tener cuidado. Muchos desarrolladores no quieren molestarse con esta complejidad adicional, o no están familiarizados con GCD o el subprocesamiento en general, por lo que evitan hacer algo en un hilo de fondo o en la cola de GCD.

Varios de los elementos que enumera en su pregunta implican interacciones con UIKit, y en general esas interacciones deben ocurrir en el hilo principal (iOS 4.x agregó la capacidad de realizar algunas funciones de dibujo en segundo plano). Recibe toque y otros eventos relacionados en el hilo principal. Si desea actualizar la mayoría de los aspectos de una interfaz, la forma más segura de hacerlo es realizando estas actualizaciones en el hilo principal.

Los temporizadores (NSTimer, CADisplayLink) pueden tener sus actualizaciones activadas en una cadena de fondo adjuntándolos a un NSRunLoop que opera en esa cadena de fondo. Rara vez ves a la gente hacer esto, pero se puede hacer. Por lo general, las personas configuran los temporizadores en el ciclo principal de ejecución, lo que hace que las devoluciones de llamadas se entreguen en el hilo principal.

Al realizar animaciones, las animaciones se ejecutarán en un hilo de fondo (verá que no se detienen mientras bloquea el hilo principal con otra cosa), pero casi siempre recibirá un bloque de finalización o devolución de llamada en el hilo principal cuando hayan terminado. Si recuerdo correctamente, hay una o dos excepciones a esto y se mencionan como tales en la documentación de Apple. Tener estas devoluciones de llamada activadas en el hilo principal es un enfoque seguro cuando se trata de desarrolladores que pueden no darse cuenta de lo que está sucediendo detrás de escena.

Dicho todo esto, hay muy buenas razones para querer agregar multiprocesamiento a su aplicación. Debido a que todas las actualizaciones de la interfaz de usuario y las interacciones táctiles ocurren en el hilo principal, si tiene algo que es computacionalmente costoso o que simplemente llevará mucho tiempo realizarlo, si lo ejecuta en su hilo principal parecerá que ha congelado su solicitud. Esta es una experiencia de usuario terrible, por lo que desea mover esta tarea a un hilo de fondo para que el usuario pueda seguir interactuando con su aplicación mientras esto sucede. Además, cada día se envían más dispositivos iOS con múltiples núcleos, y equilibrar su carga de trabajo en estos núcleos y ser eficiente con este hardware requiere un cierto grado de procesamiento simultáneo.

Las personas han escrito libros sobre las mejores prácticas al hacer código multiproceso, y aquí puede encontrar muchas preguntas al respecto, por lo que no entraré en demasiados detalles. Lo que sí puedo decirte es que deberías leer el número Concurrency Programming Guide de Apple y ver los videos de WWDC de los últimos dos años que tratan sobre Grand Central Dispatch. Con GCD, Apple ha hecho que sea mucho más fácil agregar multiprocesamiento a su aplicación de una manera eficiente y (relativamente) segura, y lo aliento a que investigue esto para sus propias aplicaciones.

Por ejemplo, tengo una aplicación de código abierto para iOS que realiza una representación detallada de estructuras moleculares.Represento cada fotograma en una cola de GCD en segundo plano porque a veces tardan más de 1/60 de segundo en procesarse, y en esos casos causan que los eventos táctiles se descarten y la interfaz tartamudee si todo estaba en el hilo principal . Además, he visto un aumento de rendimiento de hasta un 40% haciendo esto cuando se ejecuta en los dispositivos multinúcleo más nuevos. Para evitar las condiciones de carrera, elimino las interacciones con las estructuras de datos y contextos compartidos en las colas de despacho en serie, de modo que solo una acción puede usar un recurso a la vez, sin importar en qué subproceso se esté ejecutando un bloque en particular. Esto solo requirió la adición de algunas líneas de código, pero los beneficios de rendimiento y experiencia del usuario fueron enormes.

Cuestiones relacionadas