Synchronise Multiple Async Tasks With Dispatch Groups

Arvindh Sukumar
Dispatch Swift
Published in
2 min readApr 7, 2016

--

dispatch_group is a part of Apple’s Grand Central Dispatch (GCD) set of APIs that allows you to coalesce and synchronise the results of multiple asynchronous functions into a single point of execution.

With dispatch_groups, a thread is blocked until all tasks associated with that group are finished. And once they are finished, normal execution resumes, and you can be safe in the knowledge that all your asynchronous code has finished running.

Suppose you have multiple async network calls, that are not dependent on each other, but you still need to wait for all the calls to complete before proceeding. A naïve implementation of this (that I’m guilty of 😅) would look like this:

Or perhaps you’d chain one function to another, in nested callback hell. You’d lose some of the asynchronous nature of your code in that case.

With dispatch_groups though, the implementation becomes much cleaner:

Notice how there are no longer multiple unnecessary calls to a checkResults() function 😛

How it works

Before calling the different async functions, a dispatch_queue is first created. This could be an instance variable in your class, as above.

Next, in each function, before the execution becomes concurrent, a call to dispatch_group_enter is made. This tells GCD that a task was added.

When the async call returns with results, dispatch_group_leave is called. This tells GCD that a task was completed.

When all the entries are balanced out by the same number of leaves, the group is treated as finished, and the thread proceeds to the next step. Note that it is important that this balancing occurs — otherwise, the group will never finish.

Once the group is finished, there are two ways of handling it:

  • Using dispatch_group_wait: The thread pauses execution at this stage, until all tasks are complete. The next statement will only be executed after either that, or the timeout specified - whichever is earlier. This is the approach in startRequests().
  • Using a notification block: This provides you the opportunity of executing some code, on a specified thread, after all tasks are complete. This is the approach in alsoStartRequests().

And that’s all there is to it — easy synchronisation of async code, with just 3–4 simple APIs.

--

--