(iOS) dispatch_async() 与 NSOperationQueue

Posted

技术标签:

【中文标题】(iOS) dispatch_async() 与 NSOperationQueue【英文标题】:(iOS) dispatch_async() vs. NSOperationQueue 【发布时间】:2012-07-25 11:20:16 【问题描述】:

感谢斯坦福大学的 CS193p 课程(在 iTunes U 上)以及 Big Nerd Ranch 的 ios 编程书籍,我学会了 iOS 编程。在这两者中,他们建议使用dispatch_async()dispatch_get_main_queue() 等来处理线程和并发操作。然而,在 WWDC 2012 关于构建并发 UI 的会议上,演讲者建议使用NSOperationQueue

dispatch_*()NSOperationQueue 之间有什么区别,是否有任何理由(技术、性能、风格或其他)我应该使用其中一个? NSOperationQueue 只是 dispatch_async 的一个 Objective-C 包装器,还是还有更多?

【问题讨论】:

glasz 的回答几乎涵盖了所有内容,但我必须指出谁选择使用什么。如果你想在作用域内异步执行某些事情,你可以使用(块启用)gcd。但是,如果您有一个定义非常明确的任务,那么它是可重用和重复的,并且可以超出类的范围以同时执行它(和类似的任务)。您将创建NSOperations,您可以在其中正确管理特定于该任务的功能。这既可扩展又美观。 【参考方案1】:

NSOperationQueue 比 dispatch_async() 重得多,它只是以非常有限的方式基于 GCD(本质上它只是使用全局调度队列来执行其异步操作,但不使用其他 GCD 工具)。

NSOperationQueue 确实具有 GCD 未提供的其他功能,但如果您不需要这些功能,使用 GCD 会为您提供更好的性能。

【讨论】:

【参考方案2】:

NSOperation* classes 是更高级别的 api。它们对您隐藏 GCD 的较低级别的 api,以便您可以专注于完成任务。

经验法则是:先使用***别的api,然后根据您需要完成的任务进行降级。

这种方法的优点是您的代码与供应商提供的特定实现保持最不可知。 在此示例中,使用NSOperation,您将使用 Apple 的执行队列实现(使用 GCD)。如果 Apple 决定在幕后更改实现细节,他们可以在不破坏应用程序代码的情况下这样做。 一个这样的例子是 Apple 弃用了 GCD 并使用了一个完全不同的库(这不太可能,因为 Apple 创建了 GCD,而且似乎每个人都喜欢它)。

关于此事,我建议查阅以下资源:

http://nshipster.com/nsoperation/ https://cocoasamurai.blogspot.de/2009/09/guide-to-blocks-grand-central-dispatch.html https://cocoasamurai.blogspot.de/2009/09/making-nsoperation-look-like-gcd.html https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift https://developer.apple.com/documentation/foundation/operationqueue Video: Advanced NSOperations, WWDC 2015, Session 226 Sample code: Advanced NSOperations, WWDC 2015 Video: Building Responsive and Efficient Apps with GCD, WWDC 2015, Session 718

现在,关于您的具体问题:

dispatch_*() 和 NSOperationQueue 有什么区别,[...]

见上文。

[...] 是否有任何理由(技术、性能、风格或其他)我应该使用其中一个而不是另一个?

如果 NSOperation 的东西可以完成您的工作,请使用它。

NSOperationQueue 只是一个围绕 dispatch_async 的 Objective-C 包装器,还是还有更多功能?

是的,基本上是这样。加上操作依赖、轻松启动/停止等功能。

修改

说,首先使用***别的 api 可能听起来很有趣。当然,如果您需要一种在特定线程上运行代码的快速方法,您不希望编写大量样板代码,从而完全有效地使用较低级别的 C 函数:

dispatch_async(dispatch_get_main_queue(), ^
  do_something();
);

但是考虑一下:

[[NSOperationQueue mainQueue] addOperationWithBlock:^
  do_something();
];

我推荐后者,因为无论如何您将编写的大部分内容都是 Objective-C,那么为什么不接受它的表现力呢?

【讨论】:

【参考方案3】:

他们都在做同样的事情,但他们之间的主要区别是—— 我们可以在使用 NSOperation 时取消任务,而如果我们使用 GCD,那么一旦我们将任务分配到队列中,我们就无法取消它。

【讨论】:

【参考方案4】:

除了上述答案之外,NSOperation 队列相对于 GCD 的另一个优势是

1) Dependencies:- 我们可以在两个 NSOperations 之间建立依赖关系 直到它的所有依赖项都为完成返回 true,操作才会开始。

2) State of Operation:- 我们可以监控一个操作或操作队列的状态。就绪、执行或完成

3) 最大操作次数:- 我们可以指定可以同时运行的最大排队操作数

【讨论】:

以上是关于(iOS) dispatch_async() 与 NSOperationQueue的主要内容,如果未能解决你的问题,请参考以下文章

iOS:如何检查一个变量是不是在 dispatch_async 的另一个 ViewController 中改变了他的值?

dispacth_sync vs dispatch_async:iOS JSON 解析

dispatch_async 与 NSOperation 队列

将 dispatch_async 与 self 一起使用

主队列上的 dispatch_sync 与 dispatch_async

尝试将 dispatch_async 与 cocos2d 函数一起使用时出错