skip to Main Content

I’m determining to use DispatchQueue, DispatchQueue.global() or OperationQueue to run code in background thread in my app.

Let’s say I queue some tasks on these queues and then switch to another app or lock screen for a while, which results in my app being backgrounded. The app is not terminated but stay in the background.

In this scenario, is it guaranteed that all tasks in both DispatchQueue and OperationQueue will eventually complete when I return to the app? Or could the system discard some of these tasks due to memory constraints or other factors? (If the app wasn’t terminated.)

DispatchQueue.global()’s Example

DispatchQueue.global().async {
    let i = UUID().uuidString
    print("WillWork: (i)")
    DispatchQueue.global().async {
        print("DidWork: (i)") // Could it be discarded even when I return to the app?
    }
    print("ScheduleWork: (i)")
}

2

Answers


  1. There’s no guarantee that all the tasks will be completed if your app goes into the background, especially due to system resource management.

    Consider using background tasks to ensure the completion of critical tasks.
    that is beginBackgroundTask(withName:expirationHandler:) method from UIApplication

    It would help if you tried to test the app’s behaviour when in the background so you can know which task runs to completion and which gets interrupted.

    Although the first job will print "WillWork" and "ScheduleWork" right away according to the code provided, there is no assurance that "DidWork" will be printed once the application has been backgrounded, particularly if it is terminated or if resources are limited.

    Login or Signup to reply.
  2. I’m determining to use DispatchQueue, DispatchQueue.global() or OperationQueue to manage background tasks in my app.

    GCD operations are not background tasks.

    If you send an app to the background, all running (standard) operations are suspended almost instantly.
    Consider the following simple example:

    DispatchQueue.global().async {
        for step in 1...10 {
            Thread.sleep(forTimeInterval: 1)
            print("(step)")
        }
    }
    
    print("Task completed")
    

    For example, if you now send the app to the background after the output of “3”, the operation is immediately suspended.

    If you start the app again, there are 2 scenarios:

    1. The app has remained in memory and the OS wakes the app up again.
      In this scenario, the process is continued at the interrupted point and “4” is output next, followed by the remaining outputs.

    2. The OS has terminated the app and removed it from the memory.
      In this case, the app starts fresh and the operation is never completed. It is the app developer’s responsibility to resume the operation if required. Apple describes one way to do this here.

    In this scenario, is it guaranteed that all tasks in both DispatchQueue and OperationQueue will eventually complete when I return to the app?

    There is no guarantee that an operation will be completed when an app is sent to the background. The OS can terminate apps that are in the background at any time.

    If you have a task that needs to run in the background, you need to do this specifically by using background tasks or the beginBackgroundTask(withName:expirationHandler:) method.

    The latter gives your operation a limited time to complete; if this time is exceeded, the operation is aborted.

    I recommend reading the following article:
    Choosing Background Strategies for Your App

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search