So let's say I have these three functions:
func func_1() {
Task { @MainActor in
let state = try await api.get1State(v!)
print("cState func_1: \(state!)")
}
}
func func_2() {
Task { @MainActor in
let state = try await api.get2State(v!)
print("cState func_2: \(state!)")
}
}
func func_3() {
Task { @MainActor in
let state = try await api.get3State(v!)
print("cState func_3: \(state!)")
}
}
Since these function get info from api, it might take a few seconds.
How can I run func_3, after both func_1 and func_2 is done running?
I would advise avoiding
Task(which opts out of structured concurrency, and loses all the benefits that entails) unless you absolutely have to. E.g., I generally try to limitTaskto those cases where I are going from a non-asynchronous context to an asynchronous one. Where possible, I try to stay within structured concurrency.As The Swift Programming Language: Concurrency says:
And I would avoid creating functions (
func_1,func_2, andfunc_3) that fetch a value and throw it away. You would presumably return the values.If
func_1andfunc_2return different types, you could useasync let. E.g., if you're not runningfunc_3until the first two are done, perhaps it uses those values as inputs:Representing that visually using “Points of Interest” tool in Instruments:
The other pattern, if
func_1andfunc_2return the same type, is to use a task group:There are lots of permutations of the pattern, so do not get lost in the details here. The basic idea is that (a) you want to stay within structured concurrency; and (b) use
async letorTaskGroupfor those tasks you want to run in parallel.I hate to mention it, but for the sake of completeness, you can used
Taskand unstructured concurrency. From the same document I referenced above:I would avoid this because you need to handle/capture the errors manually and is somewhat brittle, but you can return the
Taskobjects, and await their respectiveresult:Note, I did not just await
func_1().resultdirectly, because you want the first two tasks to run concurrently. So launch those two tasks, save theTaskobjects, and thenawaittheir respectiveresultbefore launching the third task.But, again, your future self will probably thank you if you remain within the realm of structured concurrency.