关于 GCD 的一个常见的误解是 “once you schedule a task it can’t be canceled, you need to use the Operation API for that”。随着 iOS 8和 macOS 10.10的引入,DispatchWorkItem在一个易于使用的 API 中提供了这种确切的功能。
正如我在 Apple developer documentation中读到的 调度队列,现在您可以从执行中取消任务。为此,必须在使用 GCD over OperationQueue 时使用 DispatchWorkItem。
-
A dispatch work item has a cancel flag. If it is cancelled before
运行时,分派队列将不会执行它,并将跳过它
执行期间取消,则取消属性返回 true。在
在这种情况下,我们可以中止执行
当他们的任务完成时排队。
我采用了下面的例子从 SwiftIndia’s Medium Post 。更多的细节,请按照 苹果文档和 SwiftIndia 的中期职位。
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")