threads thread grand gcd dispatchqueue dispatch_async central async ios multithreading swift grand-central-dispatch

ios - grand - multithreading swift 4



Esperando mĂșltiples tareas de descarga asĂ­ncronas (4)

Quiero descargar algunos archivos, por ejemplo, 100 archivos, al mismo tiempo. Así que decidí agregar mis subprocesos de descarga a una cola de envío y GCD ajustará cuántos subprocesos se ejecutarán al mismo tiempo.

El problema aquí es: el bloque en dispatch_async se completará inmediatamente, porque la task se ejecutará en otro hilo. Entonces, si la longitud de las urls es 100, creará 100 hilos inmediatamente.

var queueDownloadTask = dispatch_queue_create("downloadQueue", nil) for url in urls { dispatch_async(queueDownloadTask) { let config = NSURLSessionConfiguration.defaultSessionConfiguration() let fileTransferSession = NSURLSession(configuration: config) let task = fileTransferSession.downloadTaskWithURL(url, completionHandler: { (responseUrl, response, error) -> Void in println("completed") }) task.resume() } }

¿Cómo puedo configurar el bloque en dispatch_async para esperar a que se complete la tarea de descarga? No quiero usar dispatch_semaphore , ya que solo permite ejecutar una tarea de descarga al mismo tiempo.



En Swift3,

func executeMultiTask() { //1. Create group let taskGroup = DispatchGroup() //2. Enter group taskGroup.enter() myTask1.execute(completeHandler: { // ... //3. Leave group taskGroup.leave() //< balance with taskGroup.enter() }) /* Add more tasks ... //2. Enter group taskGroup.enter() myTask2.execute(completeHandler: { //3. Leave group defer { // Use `defer` to make sure, `leave()` calls are balanced with `enter()`. taskGroup.leave() } // ... more }) */ //4. Notify when all task completed taskGroup.notify(queue: DispatchQueue.main, work: DispatchWorkItem(block: { // All tasks are done. // ... }) }


Para ampliar la respuesta de Abhinav, debes:

  1. Use dispatch_group_create() para crear un grupo.
  2. Llame a dispatch_group_enter(group) antes de comenzar cada tarea de descarga.
  3. Llame a dispatch_group_leave(group) dentro del controlador de finalización de la tarea.
  4. Luego llame a dispatch_group_notify(group, queue, ^{ ... }) para poner en cola un bloque que se ejecutará cuando se completen todas las tareas.

Puedes ver un ejemplo en esta publicación .

(Por cierto, no es cierto que hacer 100 dispatch_async s en una fila creará 100 subprocesos inmediatamente. El sistema aún conserva el control sobre cuántos subprocesos usar para satisfacer la cola. Sin embargo, su código no espera ninguna de las tareas para completar antes de que regrese, ni tampoco intenta sincronizar entre varias tareas completadas.)


Un ejemplo de trabajo objetivo-c para descargar archivos múltiples

- (void) downloadFiles: (NSMutableArray *) fileArray : (NSString *)destParentDir{ dispatch_group_t serviceGroup = dispatch_group_create(); for (id fileInfo in fileArray) { dispatch_group_enter(serviceGroup); NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *fileName = [fileInfo valueForKey:@"name"]; //Create SubDirs if needed, note that you need to exclude file name for the dirsString :) //[fileManager createDirectoryAtPath:dirsString withIntermediateDirectories:true attributes:nil error:NULL]; //Download file NSURL *url = [NSURL URLWithString:@“YOUR_FILE_URL”]; NSData *urlData = [NSData dataWithContentsOfURL:url]; if(urlData) { NSString *localPath = [NSString stringWithFormat:@"%@/%@", destParentDir, fileName]; [urlData writeToFile:localPath atomically:YES]; } dispatch_group_leave(serviceGroup); } dispatch_group_notify(serviceGroup, dispatch_get_main_queue(),^{ NSLog(@"Complete files download"); }); }