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

与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) 
       } 
      } 
     } 
    } 
+0

不相关的,如果'error'不是零或状态码不是200,那么我会确保你打电话给你的完成处理程序。你的调用者无疑想知道请求何时完成,无论成功与否。 – Rob

+0

@Rob我同意。将在我的项目中采用这一点 – modeller

您不必使用Grand Central Dispatch(GCD)调度队列与耗时URLSession请求一起使用。

如果你愿意可以使用GCD的dataTask完成处理闭包:

  1. 如果你正在做的闭包东西,本身非常耗费时间(例如,处理非常复杂的要求),而你不知道不想绑定URLSession用于处理其完成处理程序(和委托方法)的串行操作队列。这似乎不是问题(例如,解析JSON响应通常足够快,我们不必担心这一点),但只是FYI。或者,

  2. 如果完成解析dataTask的响应,如果要更新某个模型对象或更新UI。你想要在主队列上执行这些操作。

    例如,如果您的请求返回一堆物体在一些tableview中展现,你会调度模型的更新和UI的主队列:

    DispatchQueue.main.async { 
        self.objects = ... 
        self.tableView.reloadData() 
    } 
    

但你不必担心费时的URLSession请求本身。这已经是异步发生的,因此您不必将其分派到后台队列。

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

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

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

example

例如,要求其采用DispatchQueue.global.async将排队对全球队列中的任务,释放主队列更重要(UI)工作方法的。一段时间后,任务将完成,通常我们会想要对数据做些什么。如果是与用户界面相关的,我们一定要致电DispatchQueue.main.async更新信息的屏幕,或者如果它是微不足道的,不需要拨打电话和香草代码就足够了。