与DispatchQueue一起使用完成处理程序
我知道并发DispatchQueue
允许其中的代码立即返回,因此不会阻塞调用线程。这通常用于加载大量数据的后台任务。与DispatchQueue一起使用完成处理程序
我还了解到完成处理程序(例如,在URLSession
中)允许在某些任务完成后执行代码内部处理程序。
我的问题是:这是否意味着并发调度队列和完成处理程序有重叠的目的?如果我已经使用完成处理程序,那么不需要用并发调度队列来包装它吗?
例如,下面是一个使用URLSession的耗时数据加载任务,使用并发调度队列包装它是个好主意吗?
URLSession(configuration: URLSessionConfiguration.default).dataTask(with: propertiesRequest) { data, response, error in
// print("within dataTask: data: \(data), response: \(response), error: \(error)")
if let error = error {
print(error)
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("success: property task request")
do {
handler(responseDict, nil) // This is a function supplied by caller
} catch let error as NSError {
handler(nil, error)
}
}
}
}
您不必使用Grand Central Dispatch(GCD)调度队列与耗时URLSession
请求一起使用。
如果你愿意可以使用GCD的dataTask
完成处理闭包:
如果你正在做的闭包东西,本身非常耗费时间(例如,处理非常复杂的要求),而你不知道不想绑定
URLSession
用于处理其完成处理程序(和委托方法)的串行操作队列。这似乎不是问题(例如,解析JSON响应通常足够快,我们不必担心这一点),但只是FYI。或者,-
如果完成解析
dataTask
的响应,如果要更新某个模型对象或更新UI。你想要在主队列上执行这些操作。例如,如果您的请求返回一堆物体在一些tableview中展现,你会调度模型的更新和UI的主队列:
DispatchQueue.main.async { self.objects = ... self.tableView.reloadData() }
但你不必担心费时的URLSession
请求本身。这已经是异步发生的,因此您不必将其分派到后台队列。
DispatchQueue
和完成处理程序不重叠,而是可以用作处理队列的无缝解决方案。 URLSession
中的数据加载任务已经是异步的,因此无需包装在DispatchQueue
中。
DispatchQueue
- 将任务分配给特定线程以获得更好的性能(全局队列)/用户体验(主队列)。
完成处理程序 - 保证某些代码将在任务完成时运行。但是,除非另有明确说明,否则执行在当前线程上。
例如,要求其采用DispatchQueue.global.async
将排队对全球队列中的任务,释放主队列更重要(UI)工作方法的。一段时间后,任务将完成,通常我们会想要对数据做些什么。如果是与用户界面相关的,我们一定要致电DispatchQueue.main.async
更新信息的屏幕,或者如果它是微不足道的,不需要拨打电话和香草代码就足够了。
不相关的,如果'error'不是零或状态码不是200,那么我会确保你打电话给你的完成处理程序。你的调用者无疑想知道请求何时完成,无论成功与否。 – Rob
@Rob我同意。将在我的项目中采用这一点 – modeller