read

How to run in a non-main thread

Use Task.detached(priority: .background)

The following is WRONG: Task(priority: .background) – This is a child task from the current context.

Detached task is different from child tasks. It don’t use the same thread from the current context, as it has no parent.

How to run concurrently

Using async let, you can run multiple tasks in parallel.

async let listing = fetchListing()
async let favorites = fetchFavorites()

// Then await for both
let all = await [listing, favorites]

How to run concurrently with TaskGroup

TaskGroup will allow arbitrary number of tasks to run (unlike the above code).

// This task group will return the UIImage types
try await withThrowingTaskGroup(of: UIImage.self) { group in
    for url in urls {
        group.addTask {
            return try await fetchImage(from: url)
        } 
    }

    for try await image in group {
        // Handle as each image is fetched
    }
}

If you want to run task regardless of the return types, you may do so:

let task = Task {
    try await withThrowingTaskGroup(of: Void.self) { group in
        ...
        try await group.waitForAll() // Wait for all
    }
}
_ = await task.result

How to limit the number of concurrent running tasks

Let’s say you want to at most fetch 5 images at anytime, you can use next() to wait for the next task to complete before adding a new task.

// This task group will return the UIImage types
try await withThrowingTaskGroup(of: UIImage.self) { group in
    for (i, url) in urls {
        if i >= 5 {
            try await group.next() // Wait here
        }
        group.addTask {
            return try await fetchImage(from: url)
        } 
    }
    ...
}

Image

@samwize

¯\_(ツ)_/¯

Back to Home