Swift 并发 ‘gate’ 类型,用于控制异步任务的前进进度。
门可以被打开和关闭,当门关闭时,无法进入。异步任务可以在其执行过程中的适当点(由它们选择,例如检查任务取消)穿过门。如果在它们尝试进入门时门是关闭的,它们将暂停并等待门打开后再继续。
门可以从任何代码(不仅仅是异步上下文)打开或关闭。
一个示例用法是在 SwiftUI 中,您有后台任务(例如,来自 task
视图修饰符),您希望暂停和恢复以响应状态更改
struct Example: View {
let frames: NSImage
@Binding var animate: Bool {
didSet {
guard animate != oldValue else { return }
if animate {
self.animationGate.open()
} else {
self.animationGate.close()
}
}
}
@State private var animationGate = Gate(initiallyOpen: true)
@State var currentFrameIndex: Int = 0
var body: some View {
Image(nsImage: self.frames[self.currentFrameIndex])
.task {
while let _ = try? await self.animationGate.enter() {
self.currentFrameIndex = (self.currentFrameIndex + 1) % self.frames.count
try? await Task.sleep(for: .seconds(1) / 60)
}
}
}
}
请注意,如果任务被取消,enter
总是会抛出错误,因此,如果您像上面的示例中那样使用 Gate
进入,则无需手动检查取消(例如,Task.checkCancellation
/ Task.isCancelled
)。
这受到(并且部分基于)Gwendal Roué 的 Semaphore
包的启发。