(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 队列