Lop*_*per 53 iphone cocoa-touch objective-c grand-central-dispatch ios
omz*_*omz 58
NSOperationQueue早于Grand Central Dispatch,在iOS上它不使用GCD执行操作(这在Mac OS X上有所不同).它使用常规后台线程,其开销比GCD调度队列多一点.
另一方面,NSOperationQueue您可以更好地控制操作的执行方式.例如,您可以定义各个操作之间的依赖关系,这对于普通GCD队列是不可能的.也可以取消已经入队NSOperationQueue的操作(只要操作支持它).当您在GCD调度队列中排队一个块时,它肯定会在某个时刻执行.
总结一下,NSOperationQueue可能更适合可能需要取消或具有复杂依赖关系的长时间运行操作.对于应该具有最低性能和内存开销的短任务,GCD调度队列更好.
编辑:似乎文档NSOperationQueue已过时,它确实在iOS 4.0及更高版本上使用GCD.
Nit*_*rad 21
GCD是一种表示将同时执行的工作单元的轻量级方法.你没有安排这些工作单位; 系统负责为您安排日程安排.在块之间添加依赖性可能是令人头疼的问 取消或暂停块会为开发人员创建额外的工作!
与GCD相比,NSOperation和NSOperationQueue增加了一些额外开销,但您可以在各种操作之间添加依赖关系.您可以重复使用操作,取消或暂停它们.NSOperation与Key-Value Observation(KVO)兼容; 例如,您可以通过侦听NSNotificationCenter来运行NSOperation.
NSOperation和NSOperationQueue是在GDC本身之上制作的更高杠杆API,以面向对象的方式实现并发.
有关详细说明,请参阅此问题:/sf/ask/726133201/
关于 GCD 的一个常见误解是“一旦你安排了一个任务,它就不能被取消,你需要为此使用操作 API”。在 iOS 8 和 macOS 10.10中引入了DispatchWorkItem,它在一个易于使用的 API 中提供了这个确切的功能。
正如我在Apple 开发人员文档中读到的DispatchQueue,现在您可以取消执行任务。为此,您必须在通过 OperationQueue 使用 GCD 时使用DispatchWorkItem。
——
调度工作项具有取消标志。如果它在运行之前被取消,调度队列将不会执行它并跳过它。如果它在执行期间被取消,则取消属性返回 true。在这种情况下,我们可以中止执行。此外,工作项可以在其任务完成时通知队列。
注意: GCD 不执行抢先取消。要停止已经开始的工作项,您必须自己测试取消。
如下例所示,我检查如下代码
if (task?.isCancelled)! {
break
}
Run Code Online (Sandbox Code Playgroud)
苹果的定义
DispatchWorkItem 封装了要在调度队列或调度组内执行的工作。您还可以将工作项用作 DispatchSource 事件、注册或取消处理程序。
我从SwiftIndia 的 Medium post 中获取了以下示例。有关更多详细信息,请参阅Apple 文档和 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")
Run Code Online (Sandbox Code Playgroud)