将完成处理程序与 DispatchQueue 一起使用
Using completion handler together with DispatchQueue
我了解到并发 DispatchQueue
允许其中的代码立即 return,因此不会阻塞调用线程。这通常与加载大数据的后台任务一起使用。
我还了解到完成处理程序(例如,在 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)
}
}
}
}
DispatchQueue
和完成处理程序不重叠,而是可以用作处理队列的无缝解决方案。 URLSession
中的数据加载任务已经是异步的,因此不需要包装在 DispatchQueue
.
中
DispatchQueue
- 将任务分配给特定线程以获得更好的性能(全局队列)/用户体验(主队列)。
Completion Handlers - 保证某些代码会 运行 当任务完成时。但是,除非另有明确说明,否则执行在当前线程上。
例如,调用采用 DispatchQueue.global.async
的方法 A 会将任务排入全局队列,从而释放主队列以处理更重要的 (UI) 任务。一段时间后,任务就会完成,通常我们会想对数据做一些事情。如果它与 UI 相关,我们肯定希望调用 DispatchQueue.main.async
以使用信息更新屏幕,或者如果它是微不足道的,则无需进行调用,普通代码就足够了。
您不必将 Grand Central Dispatch (GCD) 调度队列与耗时的 URLSession
请求结合使用。
如果满足以下条件,您可能会在 dataTask
完成处理程序闭包中使用 GCD:
如果你在闭包内部做一些事情,本身就非常耗时(例如处理非常复杂的请求)并且你不想占用串行操作队列 URLSession
用于处理其完成处理程序(和委托方法)。这似乎不是这里的问题(例如,解析 JSON 响应通常足够快,我们不必担心这个),仅供参考。或者,
如果,当您完成解析 dataTask
的响应时,如果您想更新某些模型对象或更新 UI。您想在主队列中执行这些操作。
例如,如果您的请求返回一堆对象以显示在某些表视图中,您会将模型的更新和 UI 分派到主队列:
DispatchQueue.main.async {
self.objects = ...
self.tableView.reloadData()
}
但您不必担心耗时的 URLSession
请求本身。这已经异步发生,因此您不必将其分派到后台队列。
我了解到并发 DispatchQueue
允许其中的代码立即 return,因此不会阻塞调用线程。这通常与加载大数据的后台任务一起使用。
我还了解到完成处理程序(例如,在 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)
}
}
}
}
DispatchQueue
和完成处理程序不重叠,而是可以用作处理队列的无缝解决方案。 URLSession
中的数据加载任务已经是异步的,因此不需要包装在 DispatchQueue
.
DispatchQueue
- 将任务分配给特定线程以获得更好的性能(全局队列)/用户体验(主队列)。
Completion Handlers - 保证某些代码会 运行 当任务完成时。但是,除非另有明确说明,否则执行在当前线程上。
例如,调用采用 DispatchQueue.global.async
的方法 A 会将任务排入全局队列,从而释放主队列以处理更重要的 (UI) 任务。一段时间后,任务就会完成,通常我们会想对数据做一些事情。如果它与 UI 相关,我们肯定希望调用 DispatchQueue.main.async
以使用信息更新屏幕,或者如果它是微不足道的,则无需进行调用,普通代码就足够了。
您不必将 Grand Central Dispatch (GCD) 调度队列与耗时的 URLSession
请求结合使用。
如果满足以下条件,您可能会在 dataTask
完成处理程序闭包中使用 GCD:
如果你在闭包内部做一些事情,本身就非常耗时(例如处理非常复杂的请求)并且你不想占用串行操作队列
URLSession
用于处理其完成处理程序(和委托方法)。这似乎不是这里的问题(例如,解析 JSON 响应通常足够快,我们不必担心这个),仅供参考。或者,如果,当您完成解析
dataTask
的响应时,如果您想更新某些模型对象或更新 UI。您想在主队列中执行这些操作。例如,如果您的请求返回一堆对象以显示在某些表视图中,您会将模型的更新和 UI 分派到主队列:
DispatchQueue.main.async { self.objects = ... self.tableView.reloadData() }
但您不必担心耗时的 URLSession
请求本身。这已经异步发生,因此您不必将其分派到后台队列。