Как сказал Давид , правильно используемые группы рассылки гарантируют, что уведомление будет происходить только после того, как все задачи завершатся, чего можно достичь, вызвав leave
из отправленных блоков, как он показал вам.,Или же, поскольку ваши отправленные задачи сами по себе являются синхронными, вам не нужно вручную enter
и leave
group
, но вы можете использовать group
параметр async
метод:
let group = DispatchGroup()
let queue = DispatchQueue.global(qos: .default)
for i in 1...4 {
queue.async(group: group) {
print("? \(i)")
}
}
for i in 1...4 {
queue.async(group: group) {
print("❌ \(i)")
}
}
group.notify(queue: .main) {
print("jobs done by group")
}
Используйте group.enter()
и group.leave()
при вызове некоторого асинхронного метода, но в случае этих операторов print
вы можете просто использовать async(group:execute:)
, как показано выше.
Теперь мы решили проблему, когда блок «работы, выполненные по группам» не ожидал всех отправленных задач.Но, поскольку вы выполняете всю эту диспетчеризацию в параллельную очередь (все глобальные очереди являются параллельными очередями), у вас нет никаких гарантий, что ваши задачи будут выполнены в том порядке, который вы запрашивали.Они поставлены в очередь в строгом FIFO-режиме, но поскольку они параллельны, у вас нет никаких гарантий, когда вы нажмете соответствующие операторы print
.
Если вам нужно распечатать сообщения по порядку, вам придется использовать последовательную очередь.Например, если вы создаете собственную очередь, в отсутствие атрибута .concurrent
, последовательная очередь создаст следующее:
// create serial queue
let queue = DispatchQueue(label: "...")
// but not your own concurrent queue:
//
// let queue = DispatchQueue(label: "...", attributes: .concurrent)
//
// nor one of the global concurrent queues:
//
// let queue = DispatchQueue.global(qos: .default)
//
И если вы запустите приведенный выше кодс этой последовательной очередью вы увидите то, что искали:
? 1? 2? 3? 4❌ 1❌ 2❌ 3❌ 4задания, выполненные группой
Но, опять же, если вы используете последовательную очередь, group
будет совершенно ненужным (вы можете просто добавить задачу «завершение» как еще одну отправленную задачу)в конце последовательной очереди).Я только показываю использование последовательных очередей как способ избежать состояния гонки при отправке восьми задач в параллельную очередь.