iOS 应用程序的操作队列与调度队列
Posted
技术标签:
【中文标题】iOS 应用程序的操作队列与调度队列【英文标题】:Operation Queue vs Dispatch Queue for iOS Application 【发布时间】:2011-10-28 01:32:44 【问题描述】:-
操作队列和调度队列有什么区别?
分别在什么情况下使用更合适?
【问题讨论】:
类似问题***.com/questions/4344884/… 【参考方案1】:OperationQueue
在内部使用 Grand Central Dispatch 和 ios。
OperationQueue
让您可以更好地控制操作的执行方式。例如,您可以定义各个操作之间的依赖关系,这对于普通的 GCD 队列是不可能的。也可以取消在OperationQueue
中排队的操作(只要操作支持它)。当你在 GCD 调度队列中加入一个块时,它肯定会在某个时候被执行。
综上所述,OperationQueue
可以更适合可能需要取消或具有复杂依赖关系的长时间运行的操作。 GCD 调度队列更适合应该具有最低性能和内存开销的短任务。
【讨论】:
NSOperationQueue on iOS 4.0 and later is based on GCD. 为了清楚起见,GCD 使用 DispatchQueue,NSOperationQueue 现在更名为 OperationQueue【参考方案2】: 首选 GCD,其中任务不太复杂且需要最佳 CPU 性能。 在任务复杂且需要取消或暂停块和依赖管理的情况下,首选 NSOperationQueue。GCD 是一种轻量级的方式来表示将要同时执行的工作单元。您不安排这些工作单元;系统会为您安排日程。在块之间添加依赖关系可能会让人头疼。作为开发人员,取消或暂停区块会为您带来额外的工作!
与 GCD 相比,NSOperation 和 NSOperationQueue 增加了一点额外的开销,但是您可以在各种操作之间添加依赖关系。您可以重复使用操作、取消或暂停它们。 NSOperation 兼容 Key-Value Observation (KVO);例如,您可以通过监听 NSNotificationCenter 来启动 NSOperation。
NSOperation 和 NSOperationQueue 是更高级别的 API,建立在 GDC 本身之上,以面向对象的方式实现并发。
For detailed explanation, refer this question: https://***.com/questions/10373331/nsoperation-vs-grand-central-dispatch
【讨论】:
【参考方案3】:关于 GCD 的一个常见误解是 “一旦您安排了一项无法取消的任务,您就需要为此使用 Operation API”。在 iOS 8 和 macOS 10.10 中引入了 DispatchWorkItem,它在易于使用的 API 中提供了这一确切功能。
正如我在 Apple 开发人员文档 中阅读的关于 DispatchQueue 的内容,现在您可以取消执行任务。为此,您必须在使用 GCD 而不是 OperationQueue 时使用 DispatchWorkItem。
-
调度工作项有一个取消标志。如果之前取消 运行时,调度队列不会执行它,会跳过它。如果它 在执行过程中被取消,cancel 属性返回 true。在 这种情况下,我们可以中止执行。工作项也可以通知 任务完成后排队。
注意: GCD 不执行抢先取消。要停止已经开始的工作项,您必须自己测试是否取消。
在下面的例子中,我检查了下面的代码
if (task?.isCancelled)!
break
Apple 定义
DispatchWorkItem 封装了要在调度上执行的工作 队列或调度组内。您还可以将工作项用作 DispatchSource 事件、注册或取消处理程序。
我从 SwiftIndia's Medium post 中获取了以下示例。更多详情请关注Apple documentation 和 SwiftIndia 的 Medium Post。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
func performAsyncTaskInConcurrentQueue()
var task:DispatchWorkItem?
task = DispatchWorkItem
for i in 1...5
if Thread.isMainThread
print("task running in main thread")
else
print("task running in other thread")
if (task?.isCancelled)!
break
let imageURL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/0/07/Huge_ball_at_Vilnius_center.jpg")!
let _ = try! Data(contentsOf: imageURL)
print("\(i) finished downloading")
task = nil
/*
There are two ways to execute task on queue. Either by providing task to execute parameter or
within async block call perform() on task. perform() executes task on current queue.
*/
// concurrentQueue.async(execute: task!)
concurrentQueue.async
task?.wait(wallTimeout: .now() + .seconds(2))
// task?.wait(timeout: .now() + .seconds(2))
task?.perform()
concurrentQueue.asyncAfter(deadline: .now() + .seconds(2), execute:
task?.cancel()
)
task?.notify(queue: concurrentQueue)
print("\n############")
print("############")
print("###### Work Item Completed")
performAsyncTaskInConcurrentQueue()
print("###### Download all images asynchronously and notify on completion ######")
print("############")
print("############\n")
【讨论】:
以上是关于iOS 应用程序的操作队列与调度队列的主要内容,如果未能解决你的问题,请参考以下文章