Swift: DispatchGroup

An effortless way to handle unrelated asynchronous operations together.

Vishal V. Shekkar
Vishal V. Shekkar
3 min readNov 29, 2016

--

I recently came across a situation where I needed to wait on a couple of asynchronous operations before proceeding. These operations weren’t necessarily network-related and were not interdependent. I designed an inelegant mechanism to handle this using a few booleans and callbacks but I gave up as it was too messy and it was not scalable to support as many operations as I may add later on without adding more booleans. This led me to some interesting research online and after a while, I decided up on DispatchGroup to solve my problem.

DispatchGroup allows for aggregate synchronization of work. You can use them to submit multiple different work items and track when they all complete, even though they might run on different queues. This behavior can be helpful when progress can’t be made until all of the specified tasks are complete. — Apple’s Documentation

DispatchGroup inherits from DispatchObject which serves as the base class for a few other GCD-related Classes like DispatchQueue and DispatchSource.

Using DispatchGroup

DispatchGroup is initialized without any parameters.

let dispatchGroup = DispatchGroup()

There’s no setup required. Just call the method enter() on dispatchGroup before starting an asynchronous operation and leave() when the operation is completed.

...dispatchGroup.enter()
invokeFirstAsynchronousOperation(completion: { _ in
dispatchGroup.leave()
})
...

Do the same for the second and subsequent operations.

...dispatchGroup.enter()
invokeSecondAsynchronousOperation(completion: { _ in
dispatchGroup.leave()
})
...

Now, we’ve established ways of telling the dispatchGroup object when the operations are being started and ended. The only remaining task is to let the dispatchGroup object tell us when all the operations are completed and we’re good to go.

For this, call the notify method on the dispatchGroup object to get notified of completion.

...dispatchGroup.notify(queue: DispatchQueue.main, execute: {
//all asynchronous tasks added to this DispatchGroup are completed. Proceed as required.
})
...

The execute closure will be called when all the asynchronous tasks are completed.

Synchronous DispatchGroup Operation

The notify method provides an asynchronous way to get notified when all the operations get completed. But, if you need to wait on a particular thread synchronously until these operations complete, use the wait() method.

...dispatchGroup.enter()
invokeFirstAsynchronousOperation(completion: { _ in
dispatchGroup.leave()
})
dispatchGroup.enter()
invokeSecondAsynchronousOperation(completion: { _ in
dispatchGroup.leave()
})
dispatchGroup.wait() //Waits here on this thread until the two operations complete executing....

The wait method can accept a timeout to wait for a finite maximum amount of time before continuing execution.

Points to Note

  1. All code shown here is in Swift 3.0.1.
  2. The number of times leave() has been called on a DispatchGroup object should be equal to the number of times enter() was called. Otherwise, the execute closure in the notify method would not get called.
  3. The execute closure in the notify method would get called whenever the enter and leave counts become equal.
  4. The asynchronous operations added to the group can be executed on any queue. DispatchGroups work independent of that.
  5. The notify method has a way to specify the queue on which the execute closure needs to be invoked on. This is makes DispatchGroup very versatile.
  6. The notify method is overloaded to provided different functionality, please checkout the other method definitions to see if they will better suit your needs.
  7. Don’t Use wait() on the main thread, it will freeze the interface for the user. Either use notify or use wait() on a background thread.

Feel free to discuss about this further by writing a response.

I write about everything I find interesting and worthy enough to share.
Recommend this article if you feel more people should read it and follow me to read my future stories.

You can follow me on Twitter here.

--

--