MrTishman
MrTishman

Reputation: 87

Executing async tasks

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:

  1. Put the task in queue
  2. Execute task

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

Answers (1)

mag_zbc
mag_zbc

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

Related Questions