DispatchGroup в для цикла
Итак, у меня есть немного времени, пытаясь заставить DispatchGroup не допустить повторения цикла for до завершения длинной асинхронной операции. Большинство примеров, которые я нашел, довольно просты и понятны, но я не могу заставить мой простой тестовый пример работать так, как я ожидал.
let group = DispatchGroup()
for i in 1...3 {
group.enter()
print("INDEX \(i)")
asynchronousOperation(index: i, completion: {
print("HELLO \(i)")
self.group.leave()
})
print("OUTSIDE \(i)")
}
func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+5) {
print("DONE \(index)")
completion()
}
}
Это заканчивается печатью
START
INDEX 1
OUTSIDE 1
INDEX 2
OUTSIDE 2
INDEX 3
OUTSIDE 3
DONE 1
HELLO 1
DONE 2
HELLO 2
DONE 3
HELLO 3
Я бы ожидал, что это напечатает что-то более похожее
START
INDEX 1
OUTSIDE 1
HELLO 1
INDEX 2
OUTSIDE 2
HELLO 2
INDEX 3
OUTSIDE 3
HELLO 3
Поскольку следующий "INDEX", следующий за OUTSIDE, не будет напечатан до тех пор, пока group.leave() не будет вызван внутри asynchronousOperation()
Наверное, что-то простое, я недопонимаю - есть идеи?
2 ответа
Выполните приведенный ниже код, чтобы получить правильный вывод:
for i in 1...3 {
let semaphore = DispatchSemaphore(value: 0) // create a semaphore with a value 0. signal() will make the value 1.
print("INDEX \(i)")
asynchronousOperation(index: i, completion: {
print("HELLO \(i)")
semaphore.signal() // once you make the signal(), then only next loop will get executed.
})
print("OUTSIDE \(i)")
semaphore.wait() // asking the semaphore to wait, till it gets the signal.
}
func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now()+5) {
print("DONE \(index)")
completion()
}
}
Выход:
УКАЗАТЕЛЬ 1 ВНЕ 1 ЗАВЕРШЕН 1 ПРИВЕТ 1
УКАЗАТЕЛЬ 2 Снаружи 2 СДЕЛАНО 2 ПРИВЕТ 2
УКАЗАТЕЛЬ 3 Снаружи 3 СДЕЛАНО 3 ПРИВЕТ 3
Для этого, если я правильно понял, вы можете использовать DispatchSemaphore. Делать это:
let semaphore = DispatchSemaphore(value: 1)
for i in 1...3 {
self.semaphore.wait()
print("INDEX \(i)")
asynchronousOperation(index: i, completion: {
print("HELLO \(i)")
self.semaphore.signal()
})
print("OUTSIDE \(i)")
}
func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now()+5) {
print("DONE \(index)")
completion()
}
}