/*:#localized(key: "Overview")
 # Task Groups

 Say you're building a photo-stacking astronomy tool. To turn a faint smudge into a
 crisp galaxy, you capture the same patch of sky many times and **stack** the
 frames: combine dozens or hundreds of exposures into one clean image. Each frame
 has to be loaded and calibrated before it joins the stack, and those jobs don't
 depend on each other, so you'd love to run them all at once. But you don't know
 the count ahead of time: tonight it's 8 frames, tomorrow it's 200. In the chapter [Async Await Basics](Async%20Await%20Basics.playgroundchapter/Overview)
 you met `async let` for running a *fixed, known* handful of jobs in parallel. This
 chapter is the tool for a *dynamic* number: the **task group**.

 ---
 
 ## What you'll learn

 * Why `async let` runs out of room when the number of parallel jobs isn't fixed.
 * How to fan out `N` concurrent child tasks with `withTaskGroup` and collect their
 results.
 * Why results arrive in **completion order**, and how to put them back in order.
 * How `withThrowingTaskGroup` handles an error: it cancels the rest and rethrows.
 * The **structured guarantee** (the group never leaks a task) and how cancellation
 flows down to children.
 * A pattern to **cap** how many child tasks run at once, and why you'd want to.

 When you're ready, turn the page and we'll see exactly where `async let` runs out
 of room.

 page 1 of 9  |  [Next: Where Async Let Runs Out](@next)
 */
