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
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 fromUIApplication
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.
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:
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:
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.
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.
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