How to use TaskGroup to perform concurrent Tasks in Swift | Swift Concurrency #6

preview_player
Показать описание
In the last video, we learned async-let. However, we saw that it was a bit limited because it required a new "let" for each method that we wanted to execute. Improving on that, we turn to TaskGroup, which allows us to execute a whole group of tasks concurrency and wait for their results together!

🤙 WELCOME BACK 🤙

Рекомендации по теме
Комментарии
Автор

You are literally THE BEST TEACHER of Swift and SwiftUI out there! 🤙

MosabbirSadman
Автор

Thank you so much Nick, your videos are great and you are the best programming language teacher I've ever seen (I have MS degree in AI😂). you always explain every single point that is vague for me during my learning😍 I am eagerly waiting for more videos of you, though I know that takes so much time for you to prepare them. I really appreciate you and take my hats off to you😍😍😍😍

hamidehsheikh
Автор

Amazing, thank you so much Nick!!! I love your way of teaching, the repetition that you provide and how every video builds upon the other. With all that repetition we can become experts on these topics without even realizing it. You are a great teacher 👍🏻

andresraigoza
Автор

As always, simply amazing! Thank you. I really need more coding playtime. I really want to set the cement on these concepts.

lincolndickerson
Автор

These videos have been really useful. Plugging all the gaps in Apple's WWDC vids and documentation. Thank you.

wmblemania
Автор

Good stuff as always Nick. You're at 11K subscribers now... it's just gonna keep growing

cinquain
Автор

I just wanted to say that your video series is awesome! The content is top-notch and the quality is Amazon-level good! I really appreciate you taking the time to create this. Thank you so much!

wowo
Автор

Nick, you are amazing. Can't stop watching your bootcamps.

I must say sometimes it is weird to spend half a video doing exactly the same stuff I was doing 5 minutes ago in the last video. I can't recall content to be repeated so often in previous courses.

If I'd want to rewind Async Let I'd open previous video and do it again.

I'm not saying you should stop doing stuff the way you do, but I decided to drop a piece of a honest feedback here 😇

pasha
Автор

Thank you so much Nick for this wonderful series of videos !
Your teaching style is awesome. Even the most complex topics (like actor vs class vs struct, etc…), become cristal clear with your explanations and sample codes.
There is a lot of videos about Swift and SwiftUI on YouTube, but yours are by far my favorites one.
Moreover I wish to mention that your diction, your speech are excellent. As a French, English is not my native language, therefore some voices like the one of the great Paul Hudson (Hacking with Swift) require me to listen to very carefully in order to understand what is said. But with you, I can understand effortlessly every single word and so, I can focus all my attention only on the subject of the video.

I also have a question:
<< What is the recommend way to constrain the number of tasks run simultaneously ? >>

Suppose I have the following code to process the data associated with a bunch of URLs:

class DataProcessor {
// …

func processData(for urls: [URL]) async throws {

let dataManager = DataManager()

try await withThrowingTaskGroup(of: Data.self) { group in
for url in urls {
group.addTask {
return try await dataManager.getInfo(from: url)
}

for try await data in group {
// Do something with data
}
}
}
}
}

class DataManager {
// ...

func getInfo(from url: URL) async throws -> Data {
// return some Data
}
}

If I pass to processData(for urls: [URL]) an array of a few URLs, for instance 16, it works fine. But with an array of 800 URLs it fails because too much tasks will be spawned simultaneously.

To limit the number of tasks added to the TaskGroup over time, I end up with the code below.
It consists of 3 parts:
1. It starts by adding 8 tasks to the TaskGroup (8 is the maximum allowed in this example).
2. Then, while there is more URL to process, as soon as a task ends, the data is collected and a new task is added to the TaskGroup.
3. Finally, collects the last data (waits until all tasks has finished)
This ensure that no more than 8 tasks are run simultaneously.

I wonder if there is a better approach.

class DataProcessor {
// …

func processData(for urls: [URL]) async throws {

let dataManager = DataManager()
let maxConcurentTaskCount = 8

try await withThrowingTaskGroup(of: Data.self) { group in

func addTask(urlIndex: Int) async throws {
let url = urls[urlIndex]
group.addTask {
return try await dataManager.getInfo(from: url)
}
}

func process(_ data: Data) {
// Do something with data
}

var i = 0
// Starts the first maxConcurentTaskCount tasks
for _ in 0..<maxConcurentTaskCount {
guard i < urls.count else { break }

try await addTask(urlIndex: i)

i += 1
}

while i < urls.count {
// Collects the next available data
if let data = try await group.next() {
process(data)
}

// Adds a new taks since a task has finished
try await addTask(urlIndex: i)

i += 1
}

// Collects the last bunch of data
for try await data in group {
process(data)
}
}
}

mike
Автор

Thank you, Nick, for this wonderful playlist.

asadchattha
Автор

Thanks Nick! Great job teaching as always!

dre
Автор

Wonderful video as always~~
It's hard to understand from official video to me....
But you explain so clear!!
Thanks !!

光莒
Автор

Awesome video, I have learnt a lot from your videos. Thanks

saralgyaan
Автор

Always great explanation and contents ❤👍🏿👏🏿🔥

natgenesis
Автор

Thank you for your overall engagement. Is it stunning. But one problem in your sample could be the random order of the return. In most real live apps, you would like to have the exact Image for the given url. Returning a tuple (image, used url) could help with that. But anyway > great stuff

ronrolle
Автор

Awesome video. Need to clarify and check on one aspect. This works, but tasks are spawned concurrently, _all_ of them finish downloading, then only parent View is updated. Parent view is the one that would use the "TaskGroupBootcamp()" in its "var body: some View". This would be wrong if set of images is larger, say 200, isn't it!? It should act somewhat similar to - as user is scrolling (in say LazyVStack), network calls are made to fetch more images and populate parent View. How would that be accomplished - what would be solution scheme. What is needed is: as downloads are happening and finishing, it should update the parent View. Downloaded images should show up in LazyVStack, and those which are not yet downloaded should show with '_downloading_' or say '?' mark.

BlumeAbra
Автор

All of your videos are great! Thank you so much. 🎉

emremetilli
Автор

The reserve capacity method is good practice for space complexity

cinquain
Автор

Thank you! Understandable, easy explanation. Saved my day. :)

treboc
Автор

Two notes: 1. It is worth it to mention that TaskGroup may return nothing, and in this case childtask result, i.e. 'of:' will be Void.self. 2. Not explained why do we need second loop? Could we just add content from the second loop into the first one - in the closure of group.addTask? And next, does the task start running when we add it with group.addTask?

nickfloussov