iOS 应用程序的操作队列与调度队列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7078658/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Operation Queue vs Dispatch Queue for iOS Application
提问by Lopper
- What are the differences between Operation Queue and Dispatch Queue?
- Under what circumstances will it be more appropriate to use each?
- 操作队列和调度队列有什么区别?
- 在什么情况下使用更合适?
回答by omz
OperationQueue
internally uses Grand Central Dispatch and on iOS.
OperationQueue
内部使用 Grand Central Dispatch 和 iOS。
OperationQueue
gives you a lot more control over how your operations are executed. You can define dependencies between individual operations for example, which isn't possible with plain GCD queues. It is also possible to cancel operations that have been enqueued in an OperationQueue
(as far as the operations support it). When you enqueue a block in a GCD dispatch queue, it will definitely be executed at some point.
OperationQueue
使您可以更好地控制操作的执行方式。例如,您可以定义单个操作之间的依赖关系,这在普通 GCD 队列中是不可能的。也可以取消已入队OperationQueue
的操作(只要操作支持)。当您将一个块放入 GCD 调度队列中时,它肯定会在某个时刻执行。
To sum it up, OperationQueue
can be more suitable for long-running operations that may need to be cancelled or have complex dependencies. GCD dispatch queues are better for short tasks that should have minimum performance and memory overhead.
总结起来,OperationQueue
可以更适合可能需要取消或者有复杂依赖的长时间运行的操作。GCD 调度队列更适合应该具有最低性能和内存开销的短任务。
回答by Nitesh Borad
- Prefer GCD where task is not much complex and optimum CPU performanceis required.
- Prefer NSOperationQueue where task is complex and requires canceling or suspending a block and dependency management.
- 在任务不是很复杂且需要最佳 CPU 性能的情况下,首选 GCD 。
- 在任务复杂且需要取消或暂停块和依赖项管理的情况下,首选 NSOperationQueue 。
GCD is a lightweight way to represent units of work that are going to be executed concurrently. You don't schedule these units of work; the system takes care of scheduling for you. Adding dependency among blocks can be a headache. Canceling or suspending a block creates extra work for you as a developer!
GCD 是一种表示将要并发执行的工作单元的轻量级方式。你没有安排这些工作单元;系统会为您安排日程。在块之间添加依赖性可能会让人头疼。作为开发人员,取消或暂停块会为您带来额外的工作!
NSOperation and NSOperationQueue add a little extra overhead compared to GCD, but you can add dependency among various operations. You can re-use operations, cancel or suspend them. NSOperation is compatible with Key-Value Observation (KVO); for example, you can have an NSOperation start running by listening to NSNotificationCenter.
NSOperation 和 NSOperationQueue 与 GCD 相比增加了一点额外的开销,但是您可以在各种操作之间添加依赖项。您可以重用操作、取消或暂停它们。NSOperation 兼容键值观察(KVO);例如,你可以通过监听 NSNotificationCenter 来让 NSOperation 开始运行。
NSOperation and NSOperationQueue are higher lever APIs, made on top of the GDC itself, to achieve the concurrency in an object oriented way.
NSOperation 和 NSOperationQueue 是更高级别的 API,它们建立在 GDC 本身之上,以面向对象的方式实现并发。
详细解释请参考这个问题:https://stackoverflow.com/questions/10373331/nsoperation-vs-grand-central-dispatch
回答by kaushal
One common misconception about GCD is that “once you schedule a task it can't be canceled, you need to use the Operation API for that”. With iOS 8 & macOS 10.10 DispatchWorkItemwas introduced, which provides this exact functionality in an easy to use API.
关于 GCD 的一个常见误解是“一旦你安排了一个任务,它就不能被取消,你需要为此使用操作 API”。在 iOS 8 和 macOS 10.10中引入了DispatchWorkItem,它在一个易于使用的 API 中提供了这个确切的功能。
As I read in Apple developer documentationfor DispatchQueue, now you can cancel your task from execution. For that, you have to work with DispatchWorkItemwhile using GCD over OperationQueue.
正如我在Apple 开发人员文档中读到的DispatchQueue,现在您可以取消执行任务。为此,您必须在通过 OperationQueue 使用 GCD 时使用DispatchWorkItem。
A dispatch work item has a cancel flag. If it is cancelled before running, the dispatch queue won't execute it and will skip it. If it is cancelled during its execution, the cancel property return true. In that case, we can abort the execution. Also work items can notify a queue when their task is completed.
调度工作项具有取消标志。如果它在运行之前被取消,调度队列将不会执行它并跳过它。如果它在执行期间被取消,则取消属性返回 true。在这种情况下,我们可以中止执行。此外,工作项可以在其任务完成时通知队列。
Note:GCD doesn't perform preemptive cancelations. To stop a work item that has already started, you have to test for cancelations yourself.
注意:GCD 不执行抢先取消。要停止已经开始的工作项,您必须自己测试取消。
As in below example, I checked like the following code
如下例所示,我检查如下代码
if (task?.isCancelled)! {
break;
}
Definition by Apple
苹果的定义
A DispatchWorkItem encapsulates work to be performed on a dispatch queue or within a dispatch group. You can also use a work item as a DispatchSource event, registration, or cancellation handler.
DispatchWorkItem 封装了要在调度队列或调度组内执行的工作。您还可以将工作项用作 DispatchSource 事件、注册或取消处理程序。
I took the below example from SwiftIndia's Medium post. For more details please follow Apple documentationand SwiftIndia's Medium Post.
我从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")