Using Runloop in inside nsoperation for async tasks

413 views Asked by At

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.

1

There are 1 answers

0
mac10688 On BEST ANSWER

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.