When using GCD, we want to wait until two async blocks are executed and done before moving on to the next steps of execution. What is the best way to do that?
We tried the following, but it doesn't seem to work:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block1
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block2
});
// wait until both the block1 and block2 are done before start block3
// how to do that?
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block3
});
Use dispatch groups: see here for an example, "Waiting on Groups of Queued Tasks" in the "Dispatch Queues" chapter of Apple's iOS Developer Library's Concurrency Programming Guide
Your example could look something like this:
and could produce output like this:
The first answer is essentially correct, but if you want the very simplest way to accomplish the desired result, here's a stand-alone code example demonstrating how to do it with a semaphore (which is also how dispatch groups work behind the scenes, JFYI):
Swift 4.2 example:
Answers above are all cool, but they all missed one thing. group executes tasks(blocks) in the thread where it entered when you use
dispatch_group_enter
/dispatch_group_leave
.this runs in the created concurrent queue
demoQueue
. If i dont create any queue, it runs in main thread.and there's a third way to make tasks executed in another thread:
Of course, as mentioned you can use
dispatch_group_async
to get what you want.With Swift 5.1, Grand Central Dispatch offers many ways to solve your problem. According to your needs, you may choose one of the seven patterns shown in the following Playground snippets.
#1. Using
DispatchGroup
,DispatchGroup
'snotify(qos:flags:queue:execute:)
andDispatchQueue
'sasync(group:qos:flags:execute:)
The Apple Developer Concurrency Programming Guide states about
DispatchGroup
:#2. Using
DispatchGroup
,DispatchGroup
'swait()
,DispatchGroup
'senter()
andDispatchGroup
'sleave()
Note that you can also mix
DispatchGroup
wait()
withDispatchQueue
async(group:qos:flags:execute:)
or mixDispatchGroup
enter()
andDispatchGroup
leave()
withDispatchGroup
notify(qos:flags:queue:execute:)
.#3. Using
DispatchWorkItemFlags
barrier
andDispatchQueue
'sasync(group:qos:flags:execute:)
Grand Central Dispatch Tutorial for Swift 4: Part 1/2 article from Raywenderlich.com gives a definition for barriers:
Usage:
#4. Using
DispatchWorkItem
,DispatchWorkItemFlags
'sbarrier
andDispatchQueue
'sasync(execute:)
#5. Using
DispatchSemaphore
,DispatchSemaphore
'swait()
andDispatchSemaphore
'ssignal()
Soroush Khanlou wrote the following lines in The GCD Handbook blog post:
Apple Developer API Reference also gives the following discussion for
DispatchSemaphore
init(value:)
initializer:Usage:
#6. Using
OperationQueue
andOperation
'saddDependency(_:)
The Apple Developer API Reference states about
OperationQueue
:Usage:
#7. Using
OperationQueue
andOperationQueue
'saddBarrierBlock(_:)
(requires iOS 13)I know you asked about GCD, but if you wanted,
NSOperationQueue
also handles this sort of stuff really gracefully, e.g.: