MiddleDebuggingCommonNot answered yet
DispatchQueue.main.sync from the main thread hangs — find and fix the deadlock
The function below is called from the main thread and hangs the app instead of reloading the table. Find the cause and fix the calling code.
Constraints:
- The UI update must still run on the main thread.
- The function may also be called from a background thread later — handle both.
func reloadOnMain() {
// called from the main thread
DispatchQueue.main.sync {
tableView.reloadData()
}
}
Find and fix the bug.
main.sync blocks the caller until the block runs on the main queue. But the caller IS the main thread, now blocked, so the block never runs — a deadlock. Fix — if already on main, run the work directly; otherwise use main.async.
- ✗Believing the main queue is concurrent and can re-enter itself
- ✗Blaming
reloadData()instead of the synchronous dispatch onto main - ✗Keeping
main.syncand only guarding it with a thread check
- →Why does
main.asyncavoid the deadlock thatmain.synccauses here? - →When is calling
synconto a different queue from main safe?
The cause is main.sync from the main thread: the thread blocks waiting for the block to run on the main queue, but nothing can run it — that same thread is blocked.
func reloadOnMain() {
if Thread.isMainThread {
tableView.reloadData() // already on main — just run it
} else {
DispatchQueue.main.async { // from background — async onto main
self.tableView.reloadData()
}
}
}
Never call main.sync from code that may already be running on the main thread.