I have a use case where I need to download many files using NSURLSession.
To keep the sessiontasks from timing out I need to place them in an operation queue and limit the amount of concurrent downloads so they don't starve.
My idea is that I will load the task resume into an nsoperation and load them into an nsoperationqueue that will limit the number of concurrent activitiy.
The issue is that when I call [task resume] the code will exit and the nsoperation will consider itself complete even though I am waiting for the file to finish downloading.
Here is some code.
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest: request
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
//move the file to a permanent location
CFRunLoopStop(CFRunLoopGetCurrent());
}
//I have instantiated a class global NSOperation queue.
[imageDownloadQueue addOperationWithBlock:^void() {
[task resume];
CFRunLoopRun();
}];
How can I keep the nsoperation thread alive while I wait for the callback? I have also tried using nsrunloop and adding a port to NSMachPort. That didn't seem to help.
Also, setting the HttpMaximumConnectionsPerHost on the NSURLSession doesn't help because the timeout timer starts when I resume a task. Which means I will get more timeouts than before.
Sadly, I didn't have time for a proper fix and I needed the timeout issues fixed ASAP. I found something that did work.
//I have instantiated a class global NSOperation queue.
[imageDownloadQueue addOperationWithBlock:^void() {
[task resume];
while(task.state == NSURLSessionTaskStateRunning)
{
[NSThread sleepForTimeInterval:.1];
}
}];
Since the NSOperation works on a background thread, I was able to sleep that thread while the task is running. This keeps the thread from dying but the task will run on it's own thread and isn't blocked.