WWDC 会议超越结构化并发基础知识
11:56 - 厨房服务
func run() async throws {
try await withThrowingTaskGroup(of: Void.self) { group in
for cook in staff.keys {
group.addTask { try await cook.handleShift() }
}
group.addTask {
// keep the restaurant going until closing time
try await Task.sleep(for: shiftDuration)
}
try await group.next()
// cancel all ongoing shifts
group.cancelAll()
}
}
教练解释说,一旦厨师开始工作,我们就开始计时。当计时器结束时,我们取消所有正在进行的轮班。但
await group.next()
只等待下一个任务,这可能不是计时器。如果一名厨师下班,团队也会取消所有任务。我错过了什么还是这个例子是错误的?
这意味着
handleShift()
不会自行结束。它可能会抛出,但不会完成。
如果厨师的任务确实发生了,那么这也会导致提前结束轮班(包括取消计时器)。
这里有一个更完整的示例,以便您可以使用它并了解它是如何工作的:
actor Cook {
let id: String
let doneCount: Int
init(id: String, doneCount: Int = .max) {
self.id = id
self.doneCount = doneCount
}
var checked = 0
enum Error: Swift.Error {
case pullingTheFireAlarm
}
func handleShift() async throws {
defer { print("Shift done! \(id) is going home.")}
while !Task.isCancelled {
checked += 1
if checked >= doneCount {
print("\(id) is so done, they're sending everyone home")
throw Error.pullingTheFireAlarm
}
print("\(id) is bored of this shift. Looked at the clock \(checked) times.")
try await Task.sleep(for: .seconds(.random(in: 1..<3)))
}
}
}
let cookA = Cook(id: "A")
let cookB = Cook(id: "B")
let cookC = Cook(id: "C", doneCount: 3) // Remove `doneCount` to explore the shift ending on time
let staff = [cookA, cookB, cookC]
let shiftDuration = Duration.seconds(10)
func run() async throws {
try await withThrowingTaskGroup(of: Void.self) { group in
for cook in staff {
group.addTask { try await cook.handleShift() }
}
group.addTask {
// keep the restaurant going until closing time
try await Task.sleep(for: shiftDuration)
}
try await group.next()
// cancel all ongoing shifts
group.cancelAll()
}
}
do {
try await run()
print("Oh good. Shift ended normally")
} catch {
print("Where did everyone go? Stopped because of: \(error)")
}