[英]2017 / Swift 3.1 - GCD vs NSOperation
我正在深入了解并发性,并且已经广泛阅读了关于GCD和NSOperation
。 然而,许多帖子,如SO上的标准答案都已有几年了。
在我看来, NSOperation
主要优势曾经是以牺牲一些性能为代价的 :
特别是鉴于GCD的DispatchWorkItem
和块取消/ DispatchGroup
/ qos
,除了在开始执行或查询任务时需要能够取消任务的情况时,是否真的有动力(明智的成本)使用NSOperation
进行并发任务状态?
Apple似乎更加重视GCD,至少在他们的WWDC中(授予它比NSOperation
)。
我看到他们每个人都有自己的目的。 我刚刚在2015年WWDC上谈到了这个问题(高级NSOperations),我在这里看到了两个要点。
运行时和用户交互
从谈话:
NSOperations的运行时间比您预期的块运行时间要长一些,所以块通常需要几纳秒,最多可能需要几毫秒才能执行。
另一方面,NSOperations可以更长,从几毫秒到几分钟
他们谈论的例子是在WWDC应用程序中,其中存在一个依赖于登录用户的NSOperation。 依赖关系NSOperation提供登录视图控制器并等待用户进行身份验证。 完成后,NSOperation结束,NSOperationQueue恢复它的工作。 我认为你不想在这种情况下使用GCD。
子类
由于NSOperations只是类,因此您可以将它们子类化以从中获得更多的可重用性。 GCD无法做到这一点。
示例:(使用上面的WWDC登录方案)
您的代码库中有许多NSOperations,它们与要求对其进行身份验证的用户交互相关联。 (喜欢这个例子中的视频。)你可以扩展NSOperation来创建AuthenticatedOperation,然后让所有那些NSOperations扩展这个新类。
首先, NSOperationQueue
允许您将操作排队,即使用start
方法, cancel
方法和一些可观察属性进行某种异步操作,而使用调度队列,可以向调度队列提交块或闭包或函数队列,然后执行。
“操作”在语义上与块(或闭包,函数)在根本上是不同的。 一个操作有一个底层的异步任务,而一个块(闭包或函数)就是这样。
然而,接近NSOperation
是异步函数,例如:
func asyncTask(param: Param, completion: (T?, Error?) ->())
现在有了Futures,我们可以定义相同的异步函数,如:
func asyncTask(param: Param) -> Future<T>
这使得这种异步函数非常方便。
由于期货有像map
和flatMap
这样的组合函数,我们可以很容易地“模仿” NSOperation
的“依赖”特征,只是以更强大,更简洁和更易理解的方式。
我们还可以使用几行基于GCD的代码实现某种NSOperationQueue
,例如“TaskQueue”,并且具有基本相同的功能,如“maxConcurrentTasks”,并且可以使用它来排队任务函数 (不是操作),只需更强大,更简洁,更易于理解的方式。 ;)
为了获得可取消的操作,您需要创建NSOperation
的子类 - 同时您可以创建一个异步函数“ad-hod” - 内联。
此外,由于取消是一个独立的概念,我们可以假设,存在一些库,其实现完全基于GCD,以通常的方式解决这个问题;)它可能看起来像这样:
self.cancellationRequest = CancellationRequest()
self.asyncTask(param: param, cancellationToken: cr.token).map { result in
...
}
然后:
override func viewWillDisappear(_ animated: animated) {
super.viewWillDisappear(animated)
self.cancellationRequest.cancel()
}
所以,恕我直言,没有理由使用笨重的NSOperation
和NSOperationQueue
,并且没有理由NSOperation
的子类NSOperation
,这是非常复杂和令人惊讶的困难,除非你不关心数据NSOperation
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.