visual unitarias studio pruebas niveles interfaz herramientas ejemplo objective-c grand-central-dispatch sentestingkit

objective c - unitarias - dispatch_sync en cola principal se cuelga en prueba de unidad



pruebas unitarias java (5)

Estaba teniendo problemas para probar algunos de los principales códigos de despacho central con el marco de prueba de unidades integrado de Xcode, SenTestingKit. Pude hervir mi problema hecho a esto. Tengo una prueba de unidad que construye un bloque e intenta ejecutarlo en el hilo principal. Sin embargo, el bloque nunca se ejecuta realmente, por lo que la prueba se bloquea porque es un envío síncrono.

- (void)testSample { dispatch_sync(dispatch_get_main_queue(), ^(void) { NSLog(@"on main thread!"); }); STFail(@"FAIL!"); }

¿De qué se trata el entorno de prueba que hace que esto se cuelgue?


¿Alguna vez saldrás de la casa si esperas que salgas primero? ¡Lo adivinaste! ¡No! :]

Básicamente si:

  1. Estás en FooQueue . (no tiene que ser main_queue )
  2. Llamas al método usando sync es decir, de forma serial y quieres ejecutar en FooQueue .

¡Nunca sucederá por la misma razón por la que nunca saldrás de casa!

¡Nunca será despachado porque tiene que esperar a que salga de la cola!


El problema en su código es que no importa si usa dispatch_sync o dispatch_async , siempre se llamará a STFail() hará que la prueba falle.

Más importante aún, como explicó BJ Homer, si necesita ejecutar algo sincrónicamente en la cola principal, debe asegurarse de que no se encuentre en la cola principal o que se produzca un bloqueo. Si está en la cola principal, simplemente puede ejecutar el bloque como una función normal.

Espero que esto ayude:

- (void)testSample { __block BOOL didRunBlock = NO; void (^yourBlock)(void) = ^(void) { NSLog(@"on main queue!"); // Probably you want to do more checks here... didRunBlock = YES; }; // 2012/12/05 Note: dispatch_get_current_queue() function has been // deprecated starting in iOS6 and OSX10.8. Docs clearly state they // should be used only for debugging/testing. Luckily this is our case :) dispatch_queue_t currentQueue = dispatch_get_current_queue(); dispatch_queue_t mainQueue = dispatch_get_main_queue(); if (currentQueue == mainQueue) { blockInTheMainThread(); } else { dispatch_sync(mainQueue, yourBlock); } STAssertEquals(YES, didRunBlock, @"FAIL!"); }


Para hacer un seguimiento, ya

dispatch_get_current_queue()

ahora está en desuso, puedes usar

[NSThread isMainThread]

para ver si estás en el hilo principal.

Entonces, usando la otra respuesta anterior, podrías hacer:

- (void)testSample { BOOL __block didRunBlock = NO; void (^yourBlock)(void) = ^(void) { NSLog(@"on main queue!"); didRunBlock = YES; }; if ([NSThread isMainThread]) yourBlock(); else dispatch_sync(dispatch_get_main_queue(), yourBlock); STAssertEquals(YES, didRunBlock, @"FAIL!"); }


Si se encuentra en la cola principal y espera sincrónicamente a que esté disponible la cola principal, esperará mucho tiempo. Debes probar para asegurarte de que aún no estás en el hilo principal.


dispatch_sync ejecuta un bloque en una cola determinada y espera a que se complete. En este caso, la cola es la cola principal de envío. La cola principal ejecuta todas sus operaciones en el hilo principal, en orden FIFO (primero en entrar, primero en salir). Eso significa que siempre que llame a dispatch_sync , su nuevo bloque se colocará al final de la línea, y no se ejecutará hasta que todo lo demás antes de que termine en la cola.

El problema aquí es que el bloque que acaba de poner en cola está al final de la línea esperando para ejecutarse en el hilo principal, mientras que el método testSample se está ejecutando actualmente en el hilo principal. El bloque al final de la cola no puede acceder al hilo principal hasta que el método actual (en sí mismo) termine de usar el hilo principal. Sin embargo, dispatch_sync significa Someter un objeto de bloque para su ejecución en una cola de despacho y espera hasta que ese bloque se complete.