我发现当任务组中的任何任务因错误而失败时,任务取消状态不会传播。
在我的示例中,两个长时间运行的异步操作同时启动。这1st一个持续3sec并失败了。这2nd一个持续6sec并成功完成。两项任务均检查Task.isCancelled
完成前的状态。实际上我看到6s任务没有收到Task.isCancelled
state.
我的期望是尽快1st任务失败然后任务组发送cancel
组中所有剩余的任务。所以 6 秒任务应该通过检查Task.isCancelled
在长时间运行的异步操作的源代码下面,它通过以下方式模拟长时间运行的执行sleep()
. After sleep()
它检查Task.isCancelled
state:
func runLongOperation(key: String, sleepSec: UInt32, shouldFailWithError: Bool) async throws -> String {
try await withUnsafeThrowingContinuation { continuation in
let queue = DispatchQueue(label: "loq")
queue.async {
print(" \(key) started...")
sleep(sleepSec)
if Task.isCancelled {
print(" ...\(key) Task is cancelled")
}
if shouldFailWithError {
print(" ...\(key) finished with failure")
continuation.resume(throwing: MyError.generic)
}
else {
print(" ...\(key) finished with success")
continuation.resume(returning: key)
}
}
}
}
此异步函数在任务组中同时执行 2 个长时间运行的操作:
func runTasksGroup() async throws -> [String] {
return try await withThrowingTaskGroup(of: String.self, body: { group in
group.addTask {
return try await self.runLongOperation(key: "#1[3s]", sleepSec: 3, shouldFailWithError: true)
}
group.addTask {
return try await self.runLongOperation(key: "#2[6s]", sleepSec: 6, shouldFailWithError: false)
}
var strs = [String]()
for try await str in group {
strs += [str]
}
return strs
})
}
And runTasksGroup
函数从同步开始viewDidLoad()
功能
override func viewDidLoad() {
super.viewDidLoad()
Task {
do {
let strs = try await runTasksGroup()
print("all done with success \(strs.joined(separator: " "))")
}
catch {
print("some tasks failed")
}
}
}
输出
#1[3s] started...
#2[6s] started...
...#1[3s] finished with failure
...#2[6s] finished with success
some tasks failed
持续6秒的任务没有收到Task.isCancelled
状态,虽然 3sec 任务之前已经失败了。
谁能解释一下为什么6s任务没有取消?