You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中DispatchGroup串行执行实现问题:任务并行执行而非预期的顺序执行

Ah, I see the issue here! DispatchGroup is great for tracking when a set of tasks are all done, but it doesn't control the order in which those tasks start running. Right now, you're calling both performActivityOne and performActivityTwo back-to-back, so they're firing off asynchronously in parallel—exactly what you're seeing.

Let me break down how to fix this:

The Core Problem

DispatchGroup only cares about when you call enter() and leave(); it doesn't enforce any execution order between the tasks. Your current code triggers both async tasks immediately, so they run side by side. To get serial execution, you need to start the second task only after the first one has finished its async work.

Solution 1: Nested Completion Handlers (Simple & Straightforward)

The most direct way is to move the second task's setup into the completion closure of the first task. This ensures the second task doesn't start until the first is fully done:

let group = DispatchGroup()

// Start first task
group.enter()
print("Enter Activity One")
self.performActivityOne(param: []) {
    print("leave 1")
    group.leave()
    
    // Now start the second task *only after the first completed*
    group.enter()
    print("Enter Activity two")
    self.performActivityTwo(param: []) {
        print("leave 2")
        group.leave()
    }
}

group.notify(queue: DispatchQueue.main) {
    print("Prepare completed. I'm readyyyy")
}

With this change, your output will be exactly what you expect:

Enter Activity One
leave 1
Enter Activity two
leave 2
Prepare completed. I'm readyyyy

Solution 2: Serial Queue + Semaphores (For More Scalable Tasks)

If you have more than two tasks or want to avoid deep closure nesting, you can use a serial DispatchQueue paired with semaphores to wait for each async task to finish before moving to the next. This keeps your code flatter:

let group = DispatchGroup()
let serialQueue = DispatchQueue(label: "com.yourapp.serial.task.queue")

// Add first task to serial queue
serialQueue.async(group: group) { [weak self] in
    guard let self = self else { return }
    
    print("Enter Activity One")
    let semaphore = DispatchSemaphore(value: 0)
    
    self.performActivityOne(param: []) {
        print("leave 1")
        semaphore.signal() // Signal that the async task is done
    }
    
    semaphore.wait() // Block the serial queue until the task finishes
}

// Add second task to serial queue (it won't run until the first is done)
serialQueue.async(group: group) { [weak self] in
    guard let self = self else { return }
    
    print("Enter Activity two")
    let semaphore = DispatchSemaphore(value: 0)
    
    self.performActivityTwo(param: []) {
        print("leave 2")
        semaphore.signal()
    }
    
    semaphore.wait()
}

group.notify(queue: DispatchQueue.main) {
    print("Prepare completed. I'm readyyyy")
}

Key Takeaway

Remember: DispatchGroup is a completion tracker, not an execution order controller. To get serial execution of async tasks, you have to explicitly link the start of each subsequent task to the completion of the previous one—either via nested closures or by forcing a serial queue to wait for each async operation to finish.

内容的提问来源于stack exchange,提问作者MobX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:19:07