为什么我应该选择GCD而非NSOperation并阻止高级应用程序?

时间:2011-10-04 17:11:06

标签: objective-c ios concurrency objective-c-blocks grand-central-dispatch

Apple的Grand Central Dispatch参考文献说:

  

“...如果您的应用程序需要在Unix级别运行   系统 - 例如,如果它需要操纵文件描述符,Mach   端口,信号或定时器。 GCD不限于系统级   应用程序,但在将它用于更高级别的应用程序之前,您   应该考虑Cocoa中是否提供类似的功能(通过   NSOperation和块对象)将更容易使用或更多   适合您的需求。“。

http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

对于高级应用程序,我实际上无法想到这种情况,其中GCD的使用是强制性的,并且可以/不应该使用NSOperation。

有什么想法吗?

5 个答案:

答案 0 :(得分:55)

这里提出的观点与克里斯·汉森在其文章“When to use NSOperation vs. GCD”中所说的相同:

  

直截了当的答案是所有申请的一般准则   发展:

     

始终使用可用的最高级别抽象,然后删除   当测量显示它们是时,直到较低级别的抽象   需要的。

     

在这种特殊情况下,它意味着在编写Cocoa时   应用程序,您通常应该使用NSOperation而不是   直接使用GCD。不是因为效率的差异,而是   因为NSOperation提供了更高层次的抽象   GCD的机制。

总的来说,我同意这一点。 NSOperation和NSOperationQueue为依赖关系以及GCD阻塞和队列所不具备的一两个其他东西提供支持,并且它们抽象出了如何实现并发操作的低级细节。如果您需要该功能,NSOperation是一个非常好的方法。

然而,在使用两者之后,我发现自己用GCD块和队列替换了所有基于NSOperation的代码。我之所以这样做有两个原因:使用NSOperation进行频繁操作会产生很大的开销,我相信使用GCD块时我的代码更清晰,更具描述性。

第一个原因来自我的应用程序中的分析,我发现NSOperation对象分配和释放过程在处理小而频繁的操作时占用了大量的CPU资源,比如将OpenGL ES帧渲染到屏幕上。 GCD块完全消除了这种开销,从而显着提高了性能。

第二个原因更主观,但我相信我的代码在使用块时比NSOperations更清晰。快速捕获块允许的范围及其内联特性可以减少代码,因为您不需要创建自定义的NSOperation子类或捆绑参数以传递给操作,在我看来,更具描述性的代码,因为您可以将代码放在队列中,在它被触发的位置运行。

同样,这是一个偏好问题,但我发现自己更多地使用GCD,即使在其他更抽象的Cocoa应用程序中也是如此。

答案 1 :(得分:13)

  • 首选GCD,其中任务不复杂,需要最佳CPU性能
  • 首选NSOperationQueue,其中任务很复杂,需要取消或暂停阻止和依赖关系管理

GCD是一种表示将同时执行的工作单元的轻量级方法。你没有安排这些工作单位;系统负责为您安排日程安排。在块之间添加依赖性可能是令人头疼的问取消或暂停某个块会为开发人员创建额外的工作!

与GCD相比,NSOperation和NSOperationQueue增加了一些额外开销,但您可以在各种操作之间添加依赖关系。您可以重复使用,取消或暂停操作。 NSOperation与Key-Value Observation(KVO)兼容;例如,您可以通过侦听NSNotificationCenter来运行NSOperation。

有关详细说明,请参阅此问题:NSOperation vs Grand Central Dispatch

答案 2 :(得分:4)

好吧,NSOperation与dispatch_source_t,dispatch_io,dispatch_data_t,dispatch_semaphore_t等等无关......它的开销也有些高。

另一方面,libdispatch与操作依赖性,操作优先级(队列优先级稍有不同)或操作上的KVO等效。

答案 3 :(得分:1)

NSOperationQueue有两件事可以做GCD不做的事情:次要的是依赖性(向队列添加操作但是告诉它只在某些其他操作完成时执行),以及大的是NSOperation为您提供了一个可以在任务执行时接收消息的对象,这与GCD不同,GCD具有无法以非常有限的方式接收消息的块。你需要这两个功能,或者你不需要。如果你不这样做,使用GCD只是一件非常容易使用的事情。

这就是为什么NSOperation的有用例子总是相当复杂的原因。如果它们很简单,那么你可以使用GCD。您通常会创建一个NSOperation的子类,这将是一些重要的工作,或使用其他人创建的工作。

答案 4 :(得分:0)

我实际上只是在阅读这篇文章,而且,我相信它会让人惊讶,意见也不同。

我想不出你必须在NSOperation上使用GCD的情况,但这并不意味着这种情况不存在。但是,我同意在最佳实践编码方面的一般情绪:

如果您有一些适合该工作的工具(在这种情况下,您已经获得了NSOperation与GCD块),请使用具有最高抽象级别的类(即最高级别的API)。它不仅通常更容易使用/更少的代码,您还可以从更高级别API引入的潜在未来增强中获益。