Reputation: 16735
I'm using DispatchGroup in a class that runs on a background thread. Occasionally, I need to update the UI, so I call the following code:
dispatchGroup.notify(queue: .main) {
self.delegate?.moveTo(sender: self, location: location)
self.delegate?.updateLabel(sender: self, item: self.currentItem)
}
Unfortunately, nothing happens. However, if I call the same code, via DispatchQueue.main.async { }
, like so:
DispatchQueue.main.async {
self.delegate?.moveTo(sender: self, location: location)
self.delegate?.updateLabel(sender: self, item: self.currentItem)
}
...the delegate call gets made. I was under the impression dispatchGroup.notify(queue: .main) { }
is equivalent to DispatchQueue.main.async { }
.
Why are these not the same?
Upvotes: 4
Views: 3359
Reputation: 2930
Is your dispatchGroup
empty (i.e. have no blocks running) at the time when you call notify(queue:)
? If not, as documentation states dispatchGroup.notify(queue:)
Schedules a work item to be submitted to a queue when a group of previously submitted block objects have completed.
Which means that your closure will be executed only after the last leave()
call, when the group becomes empty. And, of course, enter()
s and leave()
s must be balanced.
Consider the following example:
let group = DispatchGroup()
group.enter()
someLongRunningTask() {
// completion callback
group.leave()
}
group.enter()
anotherLongRunningTask() {
// completion callback
group.leave()
}
group.notify(queue: .main) {
print("all set")
}
In this example all set
will be printed only after two callbacks with group.leave()
execute.
On the other hand, DispatchQueue.main.async()
immediately submits the block to the target queue but it will not necessarily start right after that – there could be running, for example, async
block with the .barrier
flag.
Update: Implementation of the example above using DispatchQueue
(hopefully, it makes things clear):
let group = DispatchGroup()
group.enter()
someLongRunningTask() {
// completion callback
group.leave()
}
group.enter()
anotherLongRunningTask() {
// completion callback
group.leave()
}
group.wait() // waits synchronously for the submitted work to complete
DispatchQueue.main.async {
print("all set")
}
Upvotes: 6