I want to download some files, for example 100 files, at the same time. So I decided to add my download threads to a dispatch queue, and GCD will adjust how many threads will run at the same time.
The problem here is: the block in dispatch_async
will be completed immediately, because task
will run on another thread. So, if urls
's length is 100, it will create 100 threads immediately.
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() } }
How can I configure the block in dispatch_async
to wait for the download task to complete? I don't want use dispatch_semaphore
, because it only allow run one download task at the same time.
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. // ... } }
To expand on Abhinav's answer, you should:
dispatch_group_create()
to create a group.dispatch_group_enter(group)
before starting each download task.dispatch_group_leave(group)
inside the task's completion handler.dispatch_group_notify(group, queue, ^{ ... })
to enqueue a block that will be executed when all the tasks are completed.You can see an example in this post.
(By the way, it's not true that doing 100 dispatch_async
s in a row will create 100 threads immediately. The system still retains control over how many threads to use to satisfy the queue. However, your code does not wait for any of the tasks to complete before it returns, nor does it attempt to synchronize between multiple tasks completing.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With