在内部使用Runloop进行异步任务

时间:2016-09-22 22:42:54

标签: ios multithreading nsurlsession nsoperation cfrunloop

我有一个用例,我需要使用NSURLSession下载许多文件。

为了防止会话任务超时,我需要将它们放在一个操作队列中,并限制并发下载量,这样它们就不会饿死。

我的想法是,我将把任务简历加载到一个nsoperation并将它们加载到一个nsoperationqueue中,这将限制并发活动的数量。

问题在于,当我调用[task resume]时,代码将退出,即使我正在等待文件完成下载,nsoperation也会认为自己已完成。

这是一些代码。

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

在等待回调时如何保持nsoperation线程处于活动状态?我也尝试过使用nsrunloop并在NSMachPort中添加一个端口。这似乎没有帮助。

此外,在NSURLSession上设置HttpMaximumConnectionsPerHost也无济于事,因为超时计时器在我恢复任务时启动。这意味着我将获得比以前更多的超时。

1 个答案:

答案 0 :(得分:1)

可悲的是,我没有时间进行适当的修复,我需要尽快修复超时问题。我找到了一些有用的东西。

    //I have instantiated a class global NSOperation queue.
[imageDownloadQueue addOperationWithBlock:^void() {
     [task resume];
     while(task.state == NSURLSessionTaskStateRunning)
    {
         [NSThread sleepForTimeInterval:.1];
    }
    }];

由于NSOperation在后台线程上工作,我可以在任务运行时睡眠该线程。这可以防止线程死亡,但任务将在它自己的线程上运行,并且不会被阻塞。