为什么下面的代码不打印“cancelled”。我检查任务取消的方式是否错误?
import UIKit
class ViewController: UIViewController {
private var task: Task<Void, Never>?
override func viewDidLoad() {
let task = Task {
do {
try await test()
} catch {
if Task.isCancelled {
print("cancelled in catch block..")
}
if let cancellationError = error as? CancellationError {
print("Task canceled..")
}
}
}
self.task = task
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
task.cancel()
}
}
func test() async throws {
while true {
if Task.isCancelled {
print("cancelled..")
throw URLError(.badURL)
}
// OUTPUT:
// "cancelled.." will not be printed
// "Task canceled.." will not be printed
// "cancelled in catch block.." will not be printed
}
}
}
但是,如果我将
if Task.isCancelled { print("cancelled in catch block..") }
放入 catch 块中,cancelled in catch block..
将按预期执行。
未打印“cancelled..”的原因是测试函数内的 Task.isCancelled 检查没有主动观察稍后由 task.cancel() 设置的取消状态。
要正确处理任务取消,您应该使用结构化并发的取消系统。你是对的,检查 catch 块内的 Task.isCancelled 确实反映了取消状态,因为它是在任务块内执行的。
import UIKit
class ViewController: UIViewController {
private var task: Task<Void, Never>?
override func viewDidLoad() {
let task = Task {
do {
try await test()
} catch {
if Task.isCancelled {
print("cancelled in catch block..")
}
if let cancellationError = error as? CancellationError {
print("Task canceled..")
}
}
}
self.task = task
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
task.cancel()
}
}
func test() async throws {
while true {
try Task.checkCancellation()
// Checking for cancellation using Task.checkCancellation()
// This actively observes the task's cancellation status
print("Checking for cancellation...")
}
}
}
通过在 test() 函数中使用 Task.checkCancellation() ,您可以正确检查任务块内的取消,并且在取消时,它将抛出 CancellationError 。然后,在 catch 块内,您可以适当地处理取消。