2012-06-01 13 views
6

Tengo 4 métodos, cada método tarda un segundo o dos antes de que el método regrese, estos métodos devuelven UIImage, necesito que estas imágenes se muestren de la manera más rápida posible.forma más rápida de ejecutar múltiples métodos al mismo tiempo

-(NSMutableArray*)prepareImages{ 
    UIImage *imageToModifyUsingUIImageCategory; 

    NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects: 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn1], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn2], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn3], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];  
    return imageArray; 
} 

Al final del método anterior, tendré 4 imágenes de esa matriz. cada método "doSomethingAndReturn" tarda uno o dos segundos, significa que mi método prepareImages terminará la ejecución aproximadamente 5 segundos. demasiado tiempo ¿eh?

mi PREGUNTA es, ¿cuál podría ser la otra forma de lograr todo esto más rápido? ¿GCD es una opción para mí? ¿cómo?

Cualquier ayuda sería muy apreciada. ¡Gracias!

Respuesta

15

Suponiendo que no le importe la carga de imágenes de forma secuencial en el fondo (en lugar de en paralelo), un simple despacho a una cola de fondo para ejecutar prepareImages hará el truco:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    NSArray *images = [self prepareImages]; 

    // now send the result back to the main thread so we can do 
    // UIKit stuff 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // set the images on your UIImageViews here... 
    }); 
}); 

Esto cargará las imágenes en una cola de segundo plano de baja prioridad, luego se enviará nuevamente al hilo principal una vez que se haya completado.

Si desea mantener esta prioridad aún más baja, puede utilizar el DISPATCH_QUEUE_PRIORITY_BACKGROUND, aunque esto solo está disponible en iOS 4.3 y posterior. Debería verificar el valor de retorno desde dispatch_get_global_queue en este caso y si devuelve 0 puede recurrir a una de las otras prioridades.

Si desea cargar cada imagen en paralelo, probablemente deba convertir sus métodos doSomethingAndReturn en las subclases NSOperation y utilizar un NSOperationQueue para ejecutarlos todos. Eso requeriría un poco más de esfuerzo para implementar. También tenga cuidado con el uso de la memoria si procesa varias imágenes grandes a la vez.

+0

gracias, estaba pensando en convertir mis métodos doSomethingAndReturn a NSOperation, pero no estaba seguro de poder probarlo. pero intentaré hacer el esfuerzo ya que me acabas de empujar :) por cierto, ¿qué hay de usar gcd con doSomethingAndReturn en lugar de NSOperation? GCD es mucho más elegante, supongo, pero ¿crees que puedo lograrlo con eso? ¡Gracias! – janusbalatbat

+2

Puede ajustar cada llamada individual a doSomethingAndReturn en su propio dispatch_async para que todas se ejecuten en paralelo. Para esperar a que todos terminen, puede crear un grupo de despacho. Consulte la documentación aquí: http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW25 –

+0

Muchas gracias tanto ... me ayudó mucho. –

1

Tengo una idea de cómo resolverlo, pero aún no probado. Estoy dibujando la solución de otros problemas que me he encontrado y resuelto:

  • Insertar NSNull-NSMutableArray como marcadores de posición.
  • dispatch_async el trabajo pesado y reemplazar la entrada correspondiente en NSMutableArray (@synchronized utilizar palabras clave para bloquear el NSMutableArray)
  • También en dispatch async función, el envío de nuevo a la cola de la función principal para actualizar la vista.
+0

gracias por la respuesta! trataré de evitar eso tan pronto como toque mi mac. – janusbalatbat

1

se puede utilizar un NSOperationQueue:

La clase NSOperationQueue regula la ejecución de un conjunto de objetos NSOperation. Después de agregarse a una cola, una operación permanece en esa cola hasta que se cancela explícitamente o termina de ejecutar su tarea. Las operaciones dentro de la cola (pero aún no se están ejecutando) están organizadas de acuerdo con niveles de prioridad y dependencias de objetos entre operaciones y se ejecutan en consecuencia. Una aplicación puede crear múltiples colas de operaciones y enviar operaciones a cualquiera de ellas.

example for a NSOperationQueue imeplementation

o una GCD Queue:

Grand Central Dispatch (GCD) colas de despacho son una poderosa herramienta para la realización de tareas. Las colas de envío le permiten ejecutar bloques de código arbitrarios de forma asincrónica o sincrónica con respecto a la persona que llama. Puede usar colas de despacho para realizar casi todas las tareas que solía realizar en hilos separados. La ventaja de las colas de despacho es que son más fáciles de usar y mucho más eficientes en la ejecución de esas tareas que el código roscado correspondiente.

example for a GCD Queue implementation

1

puede ejecutar en mismo tiempo en otro núcleo de su procesador para hacer que tratar:

NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 

Si su procesador tiene cuatro núcleos cada método será realizar en un núcleo diferente.

0

Simplemente lo hago como un ejercicio: use GCD concurrente Q para cada doSomethingAndReturn y use una serie q para controlar el número de devoluciones de llamada. Cuando la cantidad de devoluciones de llamada es igual a la cantidad de doSomethingAndReturn (s), devuelve la matriz prepareImages.

Creé el código para probar el concepto.

-(NSString *)doSomethingAndReturn1 
{ 
    for (int i=0; i<30; i++) 
    { 
     NSLog(@"soSomethingAndReturn1 i: %i", i); 
    } 
    return @"soSomethingAndReturn1"; 
} 

-(NSString *)doSomethingAndReturn2 
{ 
    for (int i=0; i<10; i++) 
    { 
     NSLog(@"soSomethingAndReturn2 i: %i", i); 
    } 
    return @"soSomethingAndReturn2"; 
} 

-(NSString *)doSomethingAndReturn3 
{ 
    for (int i=0; i<20; i++) 
    { 
     NSLog(@"soSomethingAndReturn3 i: %i", i); 
    } 
    return @"soSomethingAndReturn3"; 
} 

-(void)addToArray:(NSString *)str 
{ 
    [asyncArray addObject:str]; 
    NSLog(@"asyncArray: %@", asyncArray); 
} 

- (IBAction)buttonMultitasksPressed:(id)sender 
{ 
    dispatch_queue_t serialdQueue; 
    serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn1]]; 
     }); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn2]]; 
     }); 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      [self addToArray:[self doSomethingAndReturn3]]; 
     }); 
     dispatch_sync(serialdQueue, ^{ 
      while (!([asyncArray count] == 3)) 
      { 
       NSLog(@"not there yet count: %i", [asyncArray count]); 
      } 
     }); 

    NSLog(@"end of dispatch_sync serialQueue"); 
// return asyncArray; 
} 

Editar: 2º pensamiento: La serie no es necesaria.

Cuestiones relacionadas