与DispatchQueue一起使用完成处理程序

时间:2017-09-05 15:02:59

标签: swift concurrency grand-central-dispatch nsurlsession completionhandler

我已经了解到并发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)
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:4)

您不必将Grand Central Dispatch(GCD)调度队列与耗时的URLSession请求结合使用。

如果符合以下情况,您可以在dataTask完成处理程序关闭中使用GCD:

  1. 如果你在闭包内做某事本身非常耗时(例如处理非常复杂的请求)而且你不想占用URLSession使用的串行操作队列用于处理其完成处理程序(和委托方法)。这似乎不是问题所在(例如,解析JSON响应通常足够快,我们不必担心这一点),但仅限于FYI。或者,

  2. 如果您在解析dataTask的响应时,如果要更新某个模型对象或更新UI。你想在主队列上做那些。

    例如,如果您的请求返回了一些要在某些tableview中显示的对象,您可以将模型和UI的更新分发到主队列:

    DispatchQueue.main.async {
        self.objects = ...
        self.tableView.reloadData()
    }
    
  3. 但是,您不必担心耗时的URLSession请求本身。这已经异步发生,所以你不必将它发送到后台队列。

答案 1 :(得分:0)

DispatchQueue和完成处理程序不重叠,而是可以用作处理队列的无缝解决方案。 URLSession中的数据加载任务已经异步,因此无需包含在DispatchQueue中。

DispatchQueue - 将任务分配给特定线程以获得更好的性能(全局队列)/用户体验(主队列)。

完成处理程序 - 保证在任务完成时运行某些代码。但是,除非另有明确说明,否则执行在当前线程上。

example

例如,调用使用DispatchQueue.global.async的方法A会将任务排入全局队列,从而释放主队列以执行更重要的(UI)任务。一段时间后,任务就完成了,通常我们会想要对数据做些什么。如果它与UI相关,我们肯定希望在DispatchQueue.main.async上调用信息更新屏幕,或者如果它是微不足道的,则不需要进行调用,并且香草代码就足够了。