[英]Operation Queue vs Dispatch Queue for iOS Application
OperationQueue
在內部使用 Grand Central Dispatch 和 iOS。
OperationQueue
讓您可以更好地控制操作的執行方式。 例如,您可以定義各個操作之間的依賴關系,這對於普通的 GCD 隊列是不可能的。 也可以取消已在 OperationQueue 中排隊的OperationQueue
(只要操作支持它)。 當你在 GCD 調度隊列中加入一個塊時,它肯定會在某個時候被執行。
綜上所述, OperationQueue
可以更適合可能需要取消或具有復雜依賴關系的長時間運行的操作。 GCD 調度隊列更適合應該具有最低性能和 memory 開銷的短任務。
GCD 是一種輕量級的方式來表示將要同時執行的工作單元。 您不安排這些工作單元; 系統會為您安排日程。 在塊之間添加依賴關系可能會讓人頭疼。 作為開發人員,取消或暫停塊會為您帶來額外的工作!
與 GCD 相比,NSOperation 和 NSOperationQueue 增加了一點額外的開銷,但是您可以在各種操作之間添加依賴關系。 您可以重復使用操作、取消或暫停它們。 NSOperation 兼容 Key-Value Observation (KVO); 例如,您可以通過監聽 NSNotificationCenter 來開始運行 NSOperation。
NSOperation 和 NSOperationQueue 是更高級別的 API,建立在 GDC 本身之上,以面向 object 的方式實現並發。
詳細解釋參考這個問題:https://stackoverflow.com/questions/10373331/nsoperation-vs-grand-central-dispatch
關於 GCD 的一個常見誤解是“一旦你安排了一個不能取消的任務,你就需要為此使用 Operation API” 。 隨着 iOS 8 和 macOS 10.10 DispatchWorkItem被引入,它在一個易於使用的 API 中提供了這個確切的功能。
正如我在Apple 開發人員文檔中閱讀的DispatchQueue一樣,現在您可以取消執行任務。 為此,您必須在使用 GCD over OperationQueue 時使用DispatchWorkItem 。
-
調度工作項有一個取消標志。 如果它在運行之前被取消,調度隊列將不會執行它並會跳過它。 如果它在執行期間被取消,cancel 屬性返回 true。 在這種情況下,我們可以中止執行。 工作項也可以在其任務完成時通知隊列。
注意: GCD 不執行搶先取消。 要停止已經開始的工作項,您必須自己測試是否取消。
如下例所示,我檢查了以下代碼
if (task?.isCancelled)! {
break
}
蘋果的定義
DispatchWorkItem 封裝要在調度隊列或調度組內執行的工作。 您還可以將工作項用作 DispatchSource 事件、注冊或取消處理程序。
我從SwiftIndia 的 Medium 帖子中獲取了以下示例。 有關更多詳細信息,請關注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")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.