Возникла проблема с тем, что блок уведомлений DispatchGroup вызывался в моем приложении на ранней стадии, и этот пример игровой площадки стал экспериментом. Судя по выводу, иногда он вызывается еще до первого .leave (). Такое ощущение, что я упускаю что-то очевидное, и теперь я слишком долго на это смотрю.
let s = DispatchSemaphore(value: 1)
let dg = DispatchGroup()
func go() -> Void {
for i in 1...2 {
doWork(attemptNo: i, who: "Lily", secs: Double.random(in: 1.0...5.0))
doWork(attemptNo: i, who: "Emmie", secs: Double.random(in: 1.0...10.0))
doWork(attemptNo: i, who: "Wiley", secs: Double.random(in: 1.0...3.0))
}
}
func doWork(attemptNo: Int, who: String, secs: TimeInterval) -> Void {
DispatchQueue.global().async {
dg.enter()
print("\(who) wants to work, will wait \(secs) seconds, attempt #\(attemptNo)")
if s.wait(timeout: .now() + secs) == .timedOut {
print("\(who) was denied. No soup for me! Task #\(attemptNo) not going to happen.")
dg.leave()
return
}
let workSecs = UInt32(Int.random(in: 1...3))
print("\(who) went to work for \(workSecs) seconds on task #\(attemptNo)")
DispatchQueue.global().asyncAfter(deadline: .now() + TimeInterval(workSecs)) {
print("\(who) is sliding down the dinosaur tail. Task #\(attemptNo) all done!")
s.signal()
dg.leave()
}
}
}
go()
dg.notify(queue: .global(), execute: {print("Everyone is done.")})
Пример вывода:
Emmie wants to work, will wait 4.674405654828654 seconds, attempt #1
Lily wants to work, will wait 1.5898288206500877 seconds, attempt #1
Wiley wants to work, will wait 1.2182416407288 seconds, attempt #1
Lily wants to work, will wait 3.3225083978280647 seconds, attempt #2
Everyone is done.
Wiley wants to work, will wait 2.801577828588925 seconds, attempt #2
Emmie wants to work, will wait 8.9696422949966 seconds, attempt #2
Lily went to work for 3 seconds on task #2
Wiley was denied. No soup for me! Task #1 not going to happen.
Lily was denied. No soup for me! Task #1 not going to happen.
Wiley was denied. No soup for me! Task #2 not going to happen.
Lily is sliding down the dinosaur tail. Task #2 all done!
Emmie went to work for 3 seconds on task #1
Emmie is sliding down the dinosaur tail. Task #1 all done!
Emmie went to work for 2 seconds on task #2
Emmie is sliding down the dinosaur tail. Task #2 all done!
В этом случае «все готово» происходит почти сразу, и поскольку .leave либо не получает семафор, либо после того, как «работа» завершена, это не имеет смысла. Помогите пожалуйста.