/*:#localized(key: "WaitBlockingAlternative")
 # `wait()`: the blocking alternative

 `notify` hands you a callback. Sometimes you instead want to **stop and wait**
 right here until the group is empty. That's `wait()`, shown below.
 */
//#-editable-code
import Foundation

let group = DispatchGroup()
let prep = DispatchQueue(label: "prep", attributes: .concurrent)

for step in ["Grind beans", "Steam milk", "Pull shot"] {
    group.enter()
    prep.async {
        Thread.sleep(forTimeInterval: 0.4)
        print("Finished: \(step)")
        group.leave()
    }
}

group.wait()   // blocks THIS thread until every leave() has happened
print("All prep done: this line waited for the group")
//#-end-editable-code
/*:#localized(key: "WaitBlockingAlternative-2")
 **Watch it run:** the three `Finished:` lines print (in any order), and only
 then does `All prep done` print. Notice you did **not** need
 `needsIndefiniteExecution` here: `wait()` blocks the top-level code until the
 work completes, so the page can't end early.

 That convenience hides a trap. **`wait()` blocks the thread that calls it.**
 In a Playground's top-level code that thread is the main thread, and blocking
 it here is harmless because nothing else needs it. **In a real app, calling
 `wait()` on the main thread freezes the UI** for the entire duration, which is
 precisely the kind of freeze an earlier chapter warned you about. The fix is
 one of two things:

 * Prefer `notify(queue:)`: it's non-blocking, so nothing freezes.
 * If you truly need to block, do the waiting **on a background queue**, never
 on the main thread:

 ```swift
 DispatchQueue.global().async {
     group.wait()                 // block a background thread, fine
     DispatchQueue.main.async {
         print("Batch complete: now update the UI")
     }
 }
 ```

 You can also pass a timeout: `group.wait(timeout: .now() + 2)` returns
 `.timedOut` instead of waiting forever, which is a good habit so a stuck task
 can't hang you indefinitely.

 [Previous](@previous)  |  page 4 of 8  |  [Next: The Classic Bug: Unbalanced enter/leave](@next)
 */
