Serialization of a job in a sequential send queue is in the unit of work that is directly sent to the queue. After execution reaches the end of the presented closure (or it returns), you can execute the next block of work in the queue.
It is important to note that any other asynchronous tasks that may have been started at the close may still work (or perhaps not even started), but they are not considered.
For example, for the following code:
dispatch_async(serialQueue) { print("Start") dispatch_async(backgroundQueue) { functionThatTakes10Seconds() print("10 seconds later") } print("Done 1st") } dispatch_async(serialQueue) { print("Start") dispatch_async(backgroundQueue) { functionThatTakes10Seconds() print("10 seconds later") } print("Done 2nd") }
The result will be something like this:
Start
Done 1st
Start
Done 2nd
After 10 seconds
After 10 seconds
Please note that the first 10 second task was not completed before sending the second sequential task. Now compare:
dispatch_async(serialQueue) { print("Start") dispatch_sync(backgroundQueue) { functionThatTakes10Seconds() print("10 seconds later") } print("Done 1st") } dispatch_async(serialQueue) { print("Start") dispatch_sync(backgroundQueue) { functionThatTakes10Seconds() print("10 seconds later") } print("Done 2nd") }
The result will be something like this:
Start
After 10 seconds
Done 1st
Start
After 10 seconds
Done 2nd
Please note that this time, because the 10-second task was sent synchronously, the sequential queue was blocked, and the second task did not start until the first was completed.
In your case, there is a very good chance that the operations you certify will be sent by the asynchronous tasks themselves (since this is the nature of network operations), so the next dispatch queue itself is not enough.
You can use DispatchGroup to block the sequential send queue.
dispatch_async(serialQueue) { let dg = dispatch_group_create() dispatch_group_enter(dg) print("Start") dispatch_async(backgroundQueue) { functionThatTakes10Seconds() print("10 seconds later") dispatch_group_leave(dg) } dispatch_group_wait(dg) print("Done") }
This will lead to the conclusion
Start
After 10 seconds
Done
dg.wait() blocks the sequential queue until the number of calls to dg.leave matches the number of calls to dg.enter . If you use this method, you need to be careful that all possible completion paths for your wrapped invocation of the dg.leave operation. There are also options on dg.wait() that accept a timeout parameter.