Vincent
Vincent

Reputation: 4409

Is it possible that background work is skipped?

In Swift a lot of code runs in background threads. But some code has to be done in foreground (main thread).

DispatchQueue.main means you want to call the code inside block {} on main thread. Eg a tableReload.

let tableData = // get freshdata (A)

DispatchQueue.main.async{
  // tableReload with the new tableData (B)
}

Is it possible that (in some specific situation) part (B) is executed before part (A)?

Upvotes: 0

Views: 62

Answers (1)

Chip Jarred
Chip Jarred

Reputation: 2795

Assuming your pseudo-code represents sequential lines of actual source code, the answer is "no" in one sense, and "yes" in another sense. I'll explain what I mean, but first let's replace the comments with some function calls:

let tableData = getTableData() 

DispatchQueue.main.async {
    reloadTableData(from: tableData)
} 

The sense in which the answer is "no, A will always be called before B" is that getTableData() will 100% for sure be called before reloadTableData(from:) for the simple reason that it is called before the async call is even set up. The sequence is

  1. getTableData() is called
  2. tableData is assigned the return value from getTableData()
  3. DispatchQueue.main.async schedules the closure to be run on the next main thread run loop iteration.
  4. At some point, on the main thread, which might be different from the thread for steps 1-3, the main run loop checks if there are any scheduled tasks, and there is at least one, because you put one there, and it will execute them in order they were queued.
  5. One of the tasks is your closure, so reloadTableData(from:) is called.

The sense in which the answer is "Yes, B can execute before A" stems from being less pedantic about what you mean by executing A. If you're asking if B can begin executing before all of the work spawned by A is done, then yes. If getTableData(), that is, A, does asynchronous work, and immediately returns some kind of place-holder/future to avoid blocking, then it's entirely possible that B, which is reloadTableData(from:) could execute before the asynchronous part of A is done, or even before the asynchronous part of A starts.

However, as long as getTableData() returns the actual data you need, and not some kind of place-holder, the problematic scenario can't happen.

Upvotes: 2

Related Questions