【问题标题】:Swift DispatchGroup notify before task finishSwift DispatchGroup 在任务完成前通知
【发布时间】:2018-03-20 04:02:42
【问题描述】:

我正在使用DispatchGroup 执行任务,但在任务完成之前调用了group.notify

我的代码:

let group = DispatchGroup()
let queueImage = DispatchQueue(label: "com.image")
let queueVideo = DispatchQueue(label: "com.video")
queueImage.async(group: group) {
    sleep(2)
    print("image")
}

queueVideo.async(group: group) {
    sleep(3)
    print("video")
}

group.notify(queue: .main) {
    print("all finished.")
}

日志:

all finish.
image
video

【问题讨论】:

  • 在 Xcode 9.2 操场上运行代码会产生预期的输出,而不是问题中显示的输出。
  • 我在一个使用 Xcode 9.2 构建的实际应用程序中对其进行了测试,它在那里也能正常工作。
  • 确保您已导入 Playground 支持 @rmaddy 说它没有任何问题
  • 当我在 repl 中运行原始代码时,它确实可以工作......除了它实际上没有打印任何东西。请注意 sleep正在 工作
  • 实际上.. 现在它的行为正好相反:正在打印但立即sleep 被忽略。这很奇怪。

标签: ios swift dispatch


【解决方案1】:

更新:上面的问题实际上运行正确(正如 rmaddy 指出的那样!)

我在下面保存了这个错误的答案,以防其他人对 DispatchQueue 的 async(group:) 方法行为感到困惑,因为 Apple's swift doc on it 目前很糟糕。


组的 enter() 需要在每次调用 async() 之前调用,然后组的 leave() 需要在每个 async() 块的末尾调用,但是 within堵塞。它基本上就像一个引用计数,当它达到零(没有剩余输入)时,就会调用通知块。

let group = DispatchGroup()
let queueImage = DispatchQueue(label: "com.image")
let queueVideo = DispatchQueue(label: "com.video")

group.enter()
queueImage.async(group: group) {
    sleep(2)
    print("image")
    group.leave()
}

group.enter()
queueVideo.async(group: group) {
    sleep(3)
    print("video")
    group.leave()
}

group.notify(queue: .main) {
    print("all finished.")
}

【讨论】:

  • 那么在对async 的调用中,group 参数的意义何在?这种用法应该排除调用enterleave 的需要。
  • @rmaddy 我找不到任何文档或示例来支持你所说的,但我继续尝试(完全删除输入和离开行)并且它有效。将继续寻找文档......很好奇。将撤回我的回答。
  • 阅读相应的 Objective-C 文档。它有更多细节。
  • 我想this Apple doc 涵盖的内容足以令人信服。谢谢rmaddy!
  • 但声明“您的代码有效”的答案在 SO 上不被视为可接受的答案。没有什么可发的。这个问题实际上应该作为一个不可重现的问题关闭。
【解决方案2】:

通用答案:(Swift 5)

let yourDispatchGroup = DispatchGroup()

yourDispatchGroup.enter()
task1FunctionCall {
  yourDispatchGroup.leave() //task 1 complete
}

yourDispatchGroup.enter()
task2FunctionCall {
  yourDispatchGroup.leave() //task 2 complete
}

.. ..
yourDispatchGroup.enter()
tasknFunctionCall {
  yourDispatchGroup.leave() //task n complete
}

dispatchGroup.notify(queue: .main) {
  //This is invoked when all the tasks in the group is completed.
}

【讨论】:

    【解决方案3】:

    如果您的DispatchGrouplazy var,请尽量不要在初始化代码块内调用notify 方法。

    lazy var dispatchGroup: DispatchGroup = {
        let dispatchGroup = DispatchGroup()
        
        // not call here dispatchGroup.notify(...
    
        return dispatchGroup
    }()
    

    你需要在notify方法之前调用所有enter方法:

    dispatchGroup.enter()
    
    dispatchQueue.async(group: dispatchGroup) {
        // ...
        self.dispatchGroup.leave()
    }
    
    dispatchGroup.notify(queue: .main) {
        print("all finished.")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      相关资源
      最近更新 更多