2011-08-08 12 views
5

así que tengo este código:dispatch_async tiene retraso en algún lugar, no puede encontrar dónde. hay un problema de NSLog?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ 

//Bunch of code 

NSLog(@"Test"); 

}); 

que va y vuelve NSLog inmediatamente. Pero los resultados del código solo aparecen en la pantalla unos segundos de retraso. ¿Hay algún problema con el uso de nslog aquí, lo que significa que se llama antes de lo habitual, lo que hace que parezca rápido cuando en realidad no lo es? Estoy confundido acerca de dónde viene este retraso, ya que el NSLog está justo al final de todo el código que se ejecuta en ese momento.

Además, otra solución a mi problema, es que es posible obtener un NSLog cuando se llama a cada método (un poco como NSZombiesEnabled, supongo), así puedo asegurarme de que no hay un poco que no noté tomando hasta el dulce tiempo de respuesta de mi aplicación?

+3

¿Por qué esperaría que su registro se muestre inmediatamente? Su "montón de código" puede tardar unos segundos en ejecutarse, retrasando mucho el registro, ya que solo se ejecutará después de que el resto del código de su bloque lo tenga. –

+0

Esto es lo que me confunde. Es después de cada bit de código y, sin embargo, aparece inmediatamente, mientras que el código tarda unos segundos en mostrar los resultados en la pantalla. – Andrew

+1

OK, ¿entonces está diciendo que la declaración NSLog tiene su texto que aparece inmediatamente en la consola, pero su "montón de código" contiene otras actualizaciones de IU que no tienen efecto en la pantalla de inmediato?Si ese es el caso, ¿qué tipo de actualizaciones de UI son? ¿Se envían de forma asíncrona en el hilo principal? ¿Hay algún proceso que pueda quedar atrapado en un lazo cerrado en el hilo principal después de enviar este bloque, lo que podría prevenir las actualizaciones de UI? –

Respuesta

11

Recientemente tuve un problema similar yo mismo. Lo más probable es que sus actualizaciones retrasadas sean cosas que esté haciendo en la interfaz de usuario. Y aquí está el problema: no se está ejecutando en el hilo principal de la aplicación (también llamado el hilo de UI). Por lo tanto, lo que cambie a la interfaz de usuario no será visible hasta que ... parezca que aparece, lo que suele ocurrir con un redibujado provocado por otra cosa en la aplicación.

Lo que tienes que hacer es dentro de su cola de bloque de sus actualizaciones gráficas en el hilo de interfaz de usuario como esto:

dispatch_async(dispatch_get_main_queue(), ^{ 
     // Do GUI stuff. 
    }); 

veces su bloque podría ser grande o simplemente utilizando el código que anteriormente se ejecuta en el hilo principal, por lo que es difícil moverlo todo a un lugar específico para ejecutarlo en la cola principal. Para estas situaciones, la cola de una actualización forzada en el hilo de interfaz de usuario al final de su bloque:

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.somewidget setNeedsDisplay]; 
     [self.view setNeedsDisplay]; 
     [self.dontforgetme setNeedsDisplay]; 
    }); 

Con respecto a su "aplicación que toman el tiempo de respuesta dulce de mi aplicación", parece que son tratando de usar GDC para evitar bloquear la interfaz de usuario. Para asegurarse mediante programación que no sucede a hacer operaciones intensivas de la CPU en el hilo de interfaz de usuario, y viceversa, se corre actualizaciones interfaz gráfica de usuario en el bloque de interfaz de usuario, me he hecho las siguientes macros:

/// Stick this in code you want to assert if run on the main UI thread. 
#define DONT_BLOCK_UI() \ 
    NSAssert(![NSThread isMainThread], @"Don't block the UI thread please!") 

/// Stick this in code you want to assert if run on a background thread. 
#define BLOCK_UI() \ 
    NSAssert([NSThread isMainThread], @"You aren't running in the UI thread!") 

Como puede ver por los comentarios, tiendo a usar estas macros al comienzo de los métodos que deseo asegurar que no estoy usando por error en el lugar equivocado. He puesto estas macros y más cosas al azar en https://github.com/gradha/ELHASO-iOS-snippets que pueden serle útiles.

11

UIKit no es seguro para subprocesos. Cualquier llamada que hagas que afecte a tu UI debe realizarse en el hilo principal, o obtendrás un comportamiento extraño e impredecible. Ejemplo:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Background code that doesn't need to update the UI here 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     // UI code here 
    }); 
}); 
+0

Esta es una gran respuesta porque creo que es la forma en que la mayoría de las tareas de respuesta al evento deben suceder: pasar de la cola principal a la cola Trabajador (esencialmente) y luego regresar a la cola principal para cualquier código UIKit (lo menos posible) . Este código también es relevante, creo que: http://stackoverflow.com/a/8186206/8047 –

+0

Disculpa, solo lee la respuesta a la que me he vinculado de nuevo: si estás distribuyendo de manera asíncrona al hilo principal, no tienes preocuparse si estás en el hilo principal en primer lugar. –

+0

Esto debe aceptarse como la respuesta correcta. ¡Gracias! – NSAddict

-1

En lugar de usar // Manojo de código, debe pegar el código real, de lo contrario, es difícil encontrar su problema y perder el tiempo. Supongo que probablemente actualices ui en el "montón de código" que debería estar en el hilo principal.

Cuestiones relacionadas