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

Swift:DispatchGroup.notify在任务完成前被调用的问题求助

问题分析与解决方案

你遇到的这个情况大概率是在Playground里测试代码导致的——Playground默认会在主线程初始任务执行完毕后就停止运行,不会等待后台异步任务完成,所以group.notify的闭包会被提前触发,而后台队列里的sleep任务还没来得及执行完毕。

快速解决办法

如果是在Playground中测试,只需要在代码开头添加以下两行,让Playground保持运行状态直到所有异步任务完成:

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

代码逻辑验证(普通App环境)

如果是在iOS/macOS App中运行你这段代码,逻辑本身是完全正确的:

  • 调用async(group:)时,DispatchGroup会自动执行enter()来增加任务计数
  • 任务执行完毕后,DispatchGroup会自动调用leave()减少计数
  • 当所有加入group的任务都完成(计数归0),notify的闭包才会在主线程触发

正常运行的输出顺序应该是:

image
video
all finished.

额外开发建议

尽量避免用sleep()模拟耗时操作,它会直接阻塞当前线程,不符合GCD的异步设计思路。实际开发中更推荐用DispatchQueue.asyncAfter或者其他异步耗时API,比如:

// 手动管理group的enter/leave(因为asyncAfter是嵌套异步任务)
group.enter()
queueImage.async {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        print("image")
        group.leave()
    }
}

group.enter()
queueVideo.async {
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        print("video")
        group.leave()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:50:39