Swift Concurrency (Part 02) — Async let: Call multiple tasks asynchronously.

Habibur Rahman Ovie
3 min readDec 3, 2023

--

In this article, I will describe how to call multiple tasks asynchronously and compare the performance.

Scenario — Let's assume we have to call multiple time-consuming operations like API calling or some complex calculation and those tasks return some value that we need in future calculations. To make this example simple we use a delay function to mimic a time-consuming task.

private func delayAfter(delay: Int) async throws -> Int {
try await Task.sleep(
until: .now + .seconds(delay),
clock: .suspending
)

return delay
}

This delayAfter function is self-explanatory. It sleeps the task for a certain time and returns the time as an Int. Now let's try to call this function several times.

private func SynchronousTask() async throws{
let firstDelay = try await delayAfter(delay: 4) //1
print("First Delay\(firstDelay)") //2
let secondDelay = try await delayAfter(delay: 2) //3
print("Second Delay\(secondDelay)") //4
}

// Call the SynchronousTask function
Task {
let startTime = DispatchTime.now()

try await SynchronousTask()

let endTime = DispatchTime.now()
let elapsedTime = Double(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) / 1_000_000_000
print("ElapsedTime \(elapsedTime)")
}

In the SynchronousTask function, we call delayAfter twice. Let’s consider this as a time-consuming task. The first one needs 4 seconds and the second one needs 2 seconds to complete. This task will execute synchronously like below —
—— Here it calls the delayAfter function and waits for its completion which will take 4 seconds. After completion, it executes the second line which just prints the firstDelay variable.
— — In the third line, it calls the delayAfter function again, it waits 2 seconds and then executes the fourth line.

So basically, the SynchronousTask function executes multiple tasks synchronously one after another. In the task block, we call this function and put a timer to calculate the execution time. If we run it it will print like below.

First Delay4 //1
Second Delay2 //2
ElapsedTime 6.410721584 //3

The first line will print after 4 seconds, second line will print after 2 seconds from printing the first line. In the third line, it shows the total execution time of this task. These two tasks need about 6 seconds to complete.

Now let's try to call these Synchronous tasks Asynchronously and optimize the execution time. We need async let for this. Check the following code block.

private func ASynchronousTask() async throws{
async let firstDelay = delayAfter(delay: 4) //1
async let secondDelay = delayAfter(delay: 2) //2

print("First Delay\(try await firstDelay)") //3
print("Second Delay\(try await secondDelay)") //4
}

Task {
let startTime = DispatchTime.now()

try await ASynchronousTask()

let endTime = DispatchTime.now()
let elapsedTime = Double(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) / 1_000_000_000
print("ElapsedTime \(elapsedTime)")
}

We have refactored previous codes in the new ASynchronousTask function. Instead of waiting for a single task’s completion, we run both tasks at the same time asynchronously using the async let keyword in the 1st & 2nd number line. This will execute each task independently at the same time. In the 3rd & 4th lines, we wait for the task’s completion and print the value. The output of it is —

First Delay4 //1
Second Delay2 // 2
ElapsedTime 4.261305125 //3

Let's explain the output — As both tasks execute at the same time parallelly, it is obvious that the second task will be completed earlier than the first one. But in code, at first, we wait for the first task and then wait for the second task. So after the first task has been completed it prints the first line (after 4 seconds). Then it waits for the second task, but as the second task has already been completed ( because it needs 2 seconds to complete and it has been completed before the first one), it prints the 2nd line an instant without any delay. At last, if we see the execution time it only needs 4 seconds.

Check the first part here.
Get the full code from GitHub.
Connect me on LinkedIn.

--

--

Habibur Rahman Ovie
Habibur Rahman Ovie

No responses yet