【问题标题】:How to wait for all tasks of an NSURLSession to complete?如何等待 NSURLSession 的所有任务完成?
【发布时间】:2017-04-14 11:05:22
【问题描述】:

为什么NSURLSession操作队列在创建和恢复一个NSURLSessionTask后是空的?

有没有办法判断 NSURLSession 是否有待处理的任务?

目标是等待多个任务完成,但这不起作用:

NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithStreamedRequest:request];
[uploadTask resume];
// this prints "0"
NSLog(self.session.delegateQueue.operationCount)
// this returns immediately instead of waiting for task to complete
[self.session.delegateQueue waitUntilAllOperationsAreFinished];

【问题讨论】:

标签: ios nsurlsession nsoperationqueue nsurlsessiontask


【解决方案1】:

只要你不关心重用会话并且不介意异步做事,这很容易:

  • 在会话中致电finishTasksAndInvalidate
  • 在您的会话委托中实现URLSession:didBecomeInvalidWithError: 方法,以在最后一个任务完成后执行您需要执行的任何工作。

也就是说,您上面的代码的问题是会话在开始第一次提取之前没有任何操作,只要您的代码阻塞运行循环,就不会发生这种情况。您通常不应该尝试同步使用 NSURLSession。解决问题的方法几乎总是错误的。 :-)

【讨论】:

  • 我赞成你的回答,因为我确实没有指定重用会话。事实是,我需要重复使用它,所以我接受了不同的答案。
【解决方案2】:

我找到了一个避免会话无效的解决方案,使用建议的DispatchGroup

(答案在 Swift 中,而问题在 ObjC 中……但逻辑相同)

注意,在使用uploadTaskWithStreamedRequest:时,我们需要实现URLSessionTaskDelegatefunc urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)。因此,为了简化答案,我将演示DispatchGroupuploadTaskWithRequest:from:completionHandler: 的用法。

// strong reference to the dispatch group
let dispatchGroup = DispatchGroup()

func performManyThings() {
    for _ in 1...3 {
        let request = URLRequest(url: URL(string: "http://example.com")!)
        dispatchGroup.enter()
        let uploadTask = self.session.uploadTask(with: request, from: nil) { [weak self] _, _, _ in
            self?.dispatchGroup.leave()
        }
        uploadTask.resume()
    }
    dispatchGroup.notify(queue: .main) {
        // here, all the tasks are completed
    }
}

【讨论】:

猜你喜欢
  • 2016-01-02
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多