如何使用 Dispatch Groups 等待调用依赖于不同数据的多个函数?

How can you use Dispatch Groups to wait to call multiple functions that depend on different data?

我有三个变量,abc。我有三个带有完成块的异步函数来更新这些变量,还有另外三个函数只处理一些数据。

我正在确保工作函数等到所有数据都更新为 DispatchGroup

// The Data
var a: String?
var b: String?
var c: String?

// The Update
let group = DispatchGroup()

group.enter()
updateA() {
    group.leave()
}

group.enter()
updateB() {
    group.leave()
}

group.enter()
updateC() {
    group.leave()
}

group.wait()

// The work
doSomthingWith(a: a, b: b)
doSomethingElseWith(b: b, c: c)
doAnotherThingWith(a: a, c: c)

我希望能够做的是在参数更新后调用每个工作函数,而不是等待一切。这只是一个(显然)简化的版本。可以有更多的变量和函数。

我正在使用 Swift。非常感谢。

要单独使用调度组实现这一点,您需要 三个 相应进入和离开的调度组:

let abGroup = DispatchGroup()
let bcGroup = DispatchGroup()
let acGroup = DispatchGroup()

abGroup.enter()
abGroup.enter()
bcGroup.enter()
bcGroup.enter()
acGroup.enter()
acGroup.enter()

// When a is updated:
abGroup.leave()
acGroup.leave()

// When b is updated:
abGroup.leave()
bcGroup.leave()

// When c is updated:
acGroup.leave()
bcGroup.leave()

然后可以独立等待每组完成

abGroup.notify(queue: .main) {
    // Do something with a and b
}
bcGroup.notify(queue: .main) {
    // Do something with b and c
}
acGroup.notify(queue: .main) {
    // Do something with a and c
}

但是,这不能很好地扩展更多任务和依赖项。

更好的方法是将 Operations 添加到 OperationQueue,允许添加任意依赖项:

let queue = OperationQueue()

let updateA = BlockOperation {
    // ...
}
queue.addOperation(updateA)

let updateB = BlockOperation {
    // ...
}
queue.addOperation(updateB)

let updateC = BlockOperation {
    // ...
}
queue.addOperation(updateC)

let doSomethingWithAandB = BlockOperation {
    // ...
}
doSomethingWithAandB.addDependency(updateA)
doSomethingWithAandB.addDependency(updateB)
queue.addOperation(doSomethingWithAandB)

let doSomethingWithBandC = BlockOperation {
    // ...
}
doSomethingWithBandC.addDependency(updateB)
doSomethingWithBandC.addDependency(updateC)
queue.addOperation(doSomethingWithBandC)

let doSomethingWithAandC = BlockOperation {
    // ...
}
doSomethingWithAandC.addDependency(updateA)
doSomethingWithAandC.addDependency(updateC)
queue.addOperation(doSomethingWithAandC)

对于带有完成处理程序的异步请求,您可以使用 (local) dispatch group inside each block operation 等待 完成。

这是一个独立的例子:

import Foundation

var a: String?
var b: String?
var c: String?

let queue = OperationQueue()

let updateA = BlockOperation {
    let group = DispatchGroup()
    group.enter()
    DispatchQueue.global().asyncAfter(deadline: .now() + 1.0, execute: {
        a = "A"
        group.leave()
    })
    group.wait()
    print("updateA done")
}
queue.addOperation(updateA)

let updateB = BlockOperation {
    let group = DispatchGroup()
    group.enter()
    DispatchQueue.global().asyncAfter(deadline: .now() + 2.0, execute: {
        b = "B"
        group.leave()
    })
    group.wait()
    print("updateB done")
}
queue.addOperation(updateB)

let updateC = BlockOperation {
    let group = DispatchGroup()
    group.enter()
    DispatchQueue.global().asyncAfter(deadline: .now() + 3.0, execute: {
        c = "C"
        group.leave()
    })
    group.wait()
    print("updateC done")
}
queue.addOperation(updateC)

let doSomethingWithAandB = BlockOperation {
    print("a=", a!, "b=", b!)
}
doSomethingWithAandB.addDependency(updateA)
doSomethingWithAandB.addDependency(updateB)
queue.addOperation(doSomethingWithAandB)

let doSomethingWithAandC = BlockOperation {
    print("a=", a!, "c=", c!)
}
doSomethingWithAandC.addDependency(updateA)
doSomethingWithAandC.addDependency(updateC)
queue.addOperation(doSomethingWithAandC)

let doSomethingWithBandC = BlockOperation {
    print("b=", b!, "c=", c!)
}
doSomethingWithBandC.addDependency(updateB)
doSomethingWithBandC.addDependency(updateC)
queue.addOperation(doSomethingWithBandC)

queue.waitUntilAllOperationsAreFinished()

输出:

updateA done
updateB done
a= A b= B
updateC done
a= A c= C
b= B c= C