0

I want to push a view controller and want rest tasks to work in the background without freezing UI. but either my UI freezes or background thread executes before. a small example of my work is attached.

DispatchQueue.global(qos: .background).async {
        DispatchQueue.main.async {
            print("This is run on the main queue, after the previous code in outer block")
        }
        print("This is run on the background queue")
    }

Result:

This is run on the background queue
This is run on the main queue, after the previous code in outer block

The main queue should have executed first than the background thread.

Pathak Ayush
  • 726
  • 12
  • 24
  • 2
    1. Add `bigTasksTakingTimeInMinutes` method 2. you do not need `DispatchQueue.main.async` as you already in the main thread. – dahiya_boy Mar 05 '20 at 05:53
  • 1
    I think this will helps you to understand background thread usage -> https://stackoverflow.com/questions/24056205/how-to-use-background-thread-in-swift – emrcftci Mar 05 '20 at 05:55
  • user ap, you'll have to start from the basics to work with threading. – Fattie Mar 05 '20 at 18:32

2 Answers2

4

Your code basically executes like this:

// 1. Send this code off to the global queue to be processed async
DispatchQueue.global(qos: .background).async {
  // 3. You're here once the global queue decides it's ready to run this code

  // 4. Send this code off to the main queue to be processed async
  DispatchQueue.main.async {
    // 6. You're here once the main queue decides it's ready to run this code
    print("This is run on the main queue, after the previous code in outer block")
  }

  // 5. This is now printed
  print("This is run on the background queue")
}

// 2. whatever happens here

The reason your code runs like this is that you're dispatching everything asynchronously. this means that all you do is pass the closure off to be executed by the targetted queue at a later time, or whenever it's ready. By using async you are telling the queue you don't want to wait for this.

If you'd want your main queue bit to run immediately, you can use DispatchQueue.main.sync instead. That will block the execution of the context you're in (in this case the async closure you passed to the global queue) until the closure you're running with sync is completed.

I would typically recommend to avoid sync unless you really need it because it's far too easy to make a queue wait for itself and be locked forever (deadlock).

donnywals
  • 7,241
  • 1
  • 19
  • 27
-4

Try adding a delay to your background tasks - to see what happens

DispatchQueue.global(qos: .background).async {
    DispatchQueue.main.async {
        print("This is run on the main queue")
    }

    longRunningFunction
    print("This is run on the background queue")
}


func longRunningFunction() {
    sleep(1)
}

Now you will see the output you expected.

riklowe
  • 61
  • 1
  • 3