WWDC Swift 并发会话中的厨房服务示例令人困惑

问题描述 投票:0回答:1

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()
只等待下一个任务,这可能不是计时器。如果一名厨师下班,团队也会取消所有任务。我错过了什么还是这个例子是错误的?

swift swift-concurrency
1个回答
0
投票

这意味着

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)")
}
© www.soinside.com 2019 - 2024. All rights reserved.