Как вы можете использовать группы рассылки для ожидания вызова нескольких функций, которые зависят от разных данных? - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть три переменные, a, b и c.У меня есть три асинхронные функции с блоками завершения для обновления этих переменных и еще три функции, которые выполняют некоторую работу только с некоторыми данными.

Я гарантирую, что рабочие функции ждут, пока все данные не будут обновленыa 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.Большое спасибо заранее.

1 Ответ

0 голосов
/ 30 апреля 2018

Для достижения этого только с группами отправки вам потребуется три группы отправки, которые вводятся и оставляются соответственно:

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
}

Однако, это плохо масштабируется с большим количеством задач и зависимостей.

Лучше всего добавить Operation s к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)

Для асинхронного запроса с обработчиками завершения вы можете использовать (локальную) группу отправки внутри каждой операции блока, чтобы дождатьсязавершение.

Вот отдельный пример:

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
...