如何等待 NSURLSession 的所有任务完成?
How to wait for all tasks of an NSURLSession to complete?
为什么在创建和恢复 NSURLSessionTask 后 NSURLSession
操作队列为空?
有没有办法判断 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];
只要您不关心重用会话并且不介意异步执行操作,这就非常容易:
- 在会话中调用
finishTasksAndInvalidate
。
- 在您的会话委托中实施
URLSession:didBecomeInvalidWithError:
方法,以完成您在最后一个任务完成后需要做的任何工作。
就是说,上面代码的问题是会话在开始第一次提取之前没有任何操作,只要您的代码阻塞 运行 循环就不会发生这种情况.你通常不应该尝试同步使用 NSURLSession。解决问题的方法几乎总是错误的。 :-)
我找到了一个避免使会话无效的解决方案,使用建议的 DispatchGroup
。
(答案在 Swift 中,而问题在 ObjC 中...但逻辑相同)
注意在使用uploadTaskWithStreamedRequest:
时,我们需要实现一个URLSessionTaskDelegate
和func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
。因此,为了简化答案,我将演示 DispatchGroup
与 uploadTaskWithRequest: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
}
}
为什么在创建和恢复 NSURLSessionTask 后 NSURLSession
操作队列为空?
有没有办法判断 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];
只要您不关心重用会话并且不介意异步执行操作,这就非常容易:
- 在会话中调用
finishTasksAndInvalidate
。 - 在您的会话委托中实施
URLSession:didBecomeInvalidWithError:
方法,以完成您在最后一个任务完成后需要做的任何工作。
就是说,上面代码的问题是会话在开始第一次提取之前没有任何操作,只要您的代码阻塞 运行 循环就不会发生这种情况.你通常不应该尝试同步使用 NSURLSession。解决问题的方法几乎总是错误的。 :-)
我找到了一个避免使会话无效的解决方案,使用建议的 DispatchGroup
。
(答案在 Swift 中,而问题在 ObjC 中...但逻辑相同)
注意在使用uploadTaskWithStreamedRequest:
时,我们需要实现一个URLSessionTaskDelegate
和func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
。因此,为了简化答案,我将演示 DispatchGroup
与 uploadTaskWithRequest: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
}
}