いくつかのファイル、たとえば100個のファイルを同時にダウンロードしたい。そこで、ダウンロードスレッドをディスパッチキューに追加すると、GCDが同時に実行するスレッドの数を調整します。
ここでの問題は、task
が別のスレッドで実行されるため、dispatch_async
のブロックがすぐに完了することです。したがって、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の答えを拡張するには、以下を行う必要があります。
dispatch_group_create()
を使用してグループを作成します。dispatch_group_enter(group)
を呼び出します。dispatch_group_leave(group)
を呼び出します。dispatch_group_notify(group, queue, ^{ ... })
を呼び出して、すべてのタスクが完了したときに実行されるブロックをキューに入れます。this post で例を見ることができます。
(ところで、100 dispatch_async
sが連続すると、すぐに100個のスレッドが作成されます。システムは、キューを満たすために使用するスレッドの数を引き続き制御します。ただし、コードはタスクが完了するまで待機せずに戻り、複数のタスクの完了を同期しようとしません。)
In Swift 4、
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 at main thread queue.
taskGroup.notify(queue: .main) {
// All tasks are done.
// ...
})
}
マルチファイルをダウンロードするための実用的なObjective-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ドキュメント を参照して、ケースを解決してください。