Reputation: 87
I need help to better understanding how works concurrency in Swift.
I have the code:
DispatchQueue.main.async {
DispatchQueue.main.async {
print("A")
DispatchQueue.main.async {
print("B")
}
print("C")
}
print("D")
}
Result: D A C B
I guess "D" was first only for one reason, executing of the first Dispatch block consist of 2 steps:
And it takes more time than executing print("D"). Is that right?
When I experimented with concurrency queues, in one of the cases I got the next result: A D C B.
Why it happened?
Concurrency queue code:
DispatchQueue.global(qos: .utility).async {
DispatchQueue.global(qos: .utility).async {
print("A")
DispatchQueue.global(qos: .utility).async {
print("B")
}
print("C")
}
print("D")
}
Upvotes: 0
Views: 78
Reputation: 6992
The reason for this behaviour is that there can be many global queues with the same QoS, but there will always be only one main queue.
Your first example is predictable - it will always behave the same, because you're always dispatching tasks to the same queue - main. Tasks submitted with async
will be performed asynchronously (which means async
function will return immediately) but a new task will not start execution until a currently executed task finishes. Here's a simplified model of what happens:
Task 1:
Submit task 2
Print "D"
Task 2:
Print "A"
Submit task 3
Print "C"
Task 3:
Print "B"
Task 1
consists of submitting Task 2
and printing stuff. Task 1
is running on main queue, and Task 2
is added to the same queue. This means Task 2
cannot start until currently running task - Task 1
- finishes execution.
Seconf example is a little different. Each time you call DispatchQueue.global
, you are guaranteed to get a queue with a specific QoS, but it will not necessarily be the same queue. It would seem that the queue you dispatched print("A")
to didn't have any other tasks pending and was able to execute its work immediately, before async
method returned.
Using previously provided model - if Task 2
is added to a different queue than Task 1
is running on, then it will not need to wait for Task 1
to finish execution. But again, in this case it all depends on what queue you get each time you call DispatchQueue.global
and that is not guaranteed
Upvotes: 1