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

iOS并发编程:如何使用OperationQueue替代GCD barrier实现分组任务

问题根因

现有代码阻塞主线程的核心原因是调用addOperations(_:waitUntilFinished:)时传入了waitUntilFinished = true,这会阻塞当前调用线程(通常为主线程)直到所有传入的操作全部执行完成,和GCD barrier的非阻塞效果完全不符。

解决方案

OperationQueue原生支持操作依赖,完全可以替代GCD barrier实现「分组串行、组内并行」的需求,全程不会阻塞当前线程:

lazy var uploadQueue: OperationQueue = {
    var queue = OperationQueue()
    queue.name = "upload queue"
    queue.maxConcurrentOperationCount = 5
    return queue
}()

func workFlow(){
    // 1. 创建A组上传操作
    let a0 = BlockOperation {
        self.uploadImg(idx: "A_0")
    }
    let a1 = BlockOperation {
        Thread.sleep(forTimeInterval: 3)
        self.uploadImg(idx: "A_1")
    }
    let a2 = BlockOperation {
        self.uploadImg(idx: "A_2")
    }
    
    // 2. 创建组A完成回调操作,依赖所有A组操作执行完成
    let groupADone = BlockOperation {
        print("group A done")
    }
    [a0, a1, a2].forEach { groupADone.addDependency($0) }
    
    // 3. 创建B组上传操作,所有B组操作依赖「组A完成」操作执行完成
    let b0 = BlockOperation {
        self.uploadImg(idx: "B_0")
    }
    let b1 = BlockOperation {
        self.uploadImg(idx: "B_1")
    }
    let b2 = BlockOperation {
        self.uploadImg(idx: "B_2")
    }
    [b0, b1, b2].forEach { $0.addDependency(groupADone) }
    
    // 4. 创建组B完成回调操作,依赖所有B组操作执行完成
    let groupBDone = BlockOperation {
        print("group B done")
    }
    [b0, b1, b2].forEach { groupBDone.addDependency($0) }
    
    // 5. 所有操作一次性加入队列,无需等待,主线程直接往下执行
    uploadQueue.addOperations([a0, a1, a2, groupADone, b0, b1, b2, groupBDone], waitUntilFinished: false)
    
    // 这两句会立刻输出,不会被阻塞
    print("A: should not be hanged")
    print("B: should not be hanged")
}

func uploadImg(idx info: String){
    Thread.sleep(forTimeInterval: 1)
    print("img \(info) uploaded")
}

效果说明

  • 组内的A0/A1/A2会并行执行,全部完成后才会执行groupADone,之后B0/B1/B2才会并行执行,全部完成后执行groupBDone,和GCD barrier实现的逻辑完全一致
  • 所有操作加入队列后立刻返回,不会阻塞主线程,两个print语句会在操作调度前就输出,符合预期
    如果你的上传操作实际是异步网络请求,系统提供的BlockOperation无法正确识别异步任务的完成状态,需要自定义Operation子类,手动管理任务的isFinished/isExecuting状态标识即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:18:02