简答:
如果您想要并发执行,请使用async let 模式或任务组。
长答案:
你说:
但是下面的语句会并行运行 do 和 stuff 正确吗?
await (do(), stuff())
不,他们不会。
这是最好的经验说明:
- 使任务花费足够的时间,以便容易表现出并发行为;和
- 在 Instruments 中使用“Points of Interest”工具(例如,通过选择“Time Profiler”模板)以图形方式表示随时间变化的间隔。
考虑这段代码,使用元组方法:
import os.log
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: .pointsOfInterest)
还有:
func example() async {
let values = await (self.doSomething(), self.doSomethingElse())
print(values)
}
func doSomething() async -> Int {
spin(#function)
return 1
}
func doSomethingElse() async -> Int {
spin(#function)
return 42
}
func spin(_ name: StaticString) {
let id = OSSignpostID(log: log)
os_signpost(.begin, log: log, name: name, signpostID: id, "begin")
let start = CACurrentMediaTime()
while CACurrentMediaTime() - start < 1 { } // spin for one second
os_signpost(.end, log: log, name: name, signpostID: id, "end")
}
这导致图表显示它没有同时发生:
鉴于:
func example() async {
async let foo = self.doSomething()
async let bar = self.doSomethingElse()
let values = await (foo, bar)
print(values)
}
这确实会导致并发执行:
现在,在上面的示例中,我更改了函数以便它们返回值(因为这确实是使用元组具有实际意义的唯一上下文)。
但如果它们不返回值并且您希望它们并行运行,则可以使用任务组:
func experiment() async {
await withTaskGroup(of: Void.self) { group in
group.addTask { await self.doSomething() }
group.addTask { await self.doSomethingElse() }
}
}
func doSomething() async {
spin(#function)
}
func doSomethingElse() async {
spin(#function)
}
这会导致它们并行运行的相同图表。
您也可以只创建 Task 实例,然后创建 await 它们:
func experiment() async {
async let task1 = Task { await doSomething() }
async let task2 = Task { await doSomethingElse() }
_ = await task1
_ = await task2
}
但是当正在创建的任务数量在编译时可能未知时,任务组提供了更大的灵活性。