let group = DispatchGroup()
someQueue.async(group: group) { ... your work ... }
someQueue.async(group: group) { ... more work .... }
someOtherQueue.async(group: group) { ... other work ... }
group.notify(queue: DispatchQueue.main) { [weak self] in
self?.textLabel.text = "All jobs have completed"
}
위의 예제 코드에서 볼 수 있듯이 group들은 하나의 dispatch queue에 강하게 연결되어있지 않습니다. 하나의 group을 실행해야하는 task의 우선순위에 따라 여러 queue에 제출할 수 있습니다. DispatchGroups는 제출된 모든 작업이 끝나는대로 notify를 받을 수 있게 notify(queue:) 메서드를 제공합니다.
Note: notification 자체는 async입니다. 제출된 작업들이 아직 완료되기전에, notify를 호출한 후 더 많은 작업들을 제출할 수 있습니다.
let group = DispatchGroup()
someQueue.async(group: group) { ... }
someQueue.async(group: group) { ... }
someOtherQueue.async(group: group) { ... }
if group.wait(timeout: .now() + 60) == .timedOut {
print("The jobs didn’t finish in 60 seconds")
}
Note: 현재 thread를 block한다는 것을 잊지마세요. main queue에서 절대로 wait메서드를 호출하지 마세요
queue.dispatch(group: group) {
// count is 1
group.enter()
// count is 2
someAsyncMethod {
defer { group.leave() }
// Perform your work here,
// count goes back to 1 once complete
}
}
group.enter()를 통해 dispatch group에 실행중인 다른 코드블럭(group에 전체적인 완료상태에 카운팅 되어야하는)이 있다는 것을 알려줍니다. 물론 해당하는 group.leave()와 페어링해야합니다. 그렇지 않으면 완료신호를 받을 수 없습니다. 오류 상태에서도 leave를 호출해야하기 때문에, defer문을 사용하면 어떻게 closure의 종료하는지와 상관없이 group.leave()가 실행됩니다.
func myAsyncAdd(
lhs: Int,
rhs: Int,
completion: @escaping (Int) -> Void) {
// Lots of cool code here
completion(lhs + rhs)
}
func myAsyncAddForGroups(
group: DispatchGroup,
lhs: Int,
rhs: Int,
completion: @escaping (Int) -> Void) {
group.enter()
myAsyncAdd(first: first, second: second) { result in
defer { group.leave() }
completion(result)
}
}
let semaphore = DispatchSemaphore(value: 4)
for i in 1...10 { queue.async(group: group) {
semaphore.wait()
defer { semaphore.signal() }
print("Downloading image \(i)")
// Simulate a network wait
Thread.sleep(forTimeInterval: 3)
print("Downloaded image \(i)")
}
}