等待多个异步下载任务

我想同时下载一些文件,例如100个文件。 所以我决定将我的下载线程添加到调度队列,GCD将调整同时运行的线程数。

这里的问题是: dispatch_async的块将立即完成,因为task将在另一个线程上运行。 因此,如果urls长度为100,则会立即创建100个线程。

 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() } } 

如何在dispatch_async配置块以等待下载任务完成? 我不想使用dispatch_semaphore ,因为它只允许同时运行一个下载任务。

为了扩展Abhinav的答案,你应该:

  1. 使用dispatch_group_create()创建一个组。
  2. 在开始每个下载任务之前调用dispatch_group_enter(group)
  3. 在任务的完成处理程序中调用dispatch_group_leave(group)
  4. 然后调用dispatch_group_notify(group, queue, ^{ ... })以排队将在所有任务完成时执行的块。

你可以在这篇文章中看到一个例子。

(顺便说一下,连续执行100个dispatch_async并不会立即创建100个线程。系统仍然可以控制用于满足队列的线程数。但是,您的代码不会等待任何任务在它返回之前完成,也不会尝试在完成多个任务之间进行同步。)

在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. // ... }) } 

下载多个文件的工作目标-c示例

 - (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"); }); } 

你应该使用dispatch_group_t 。 请参阅Apple文档以解决您的案例。