MiddleДебаггингЧастоЕщё не отвечали
DispatchQueue.main.sync с главного потока зависает — найдите и исправьте взаимоблокировку
Функция ниже вызывается с главного потока и вешает приложение вместо перезагрузки таблицы. Найдите причину и исправьте вызывающий код.
Ограничения:
- Обновление UI всё равно должно идти на главном потоке.
- Функцию позже могут вызвать и с фонового потока — обработайте оба случая.
func reloadOnMain() {
// вызывается с главного потока
DispatchQueue.main.sync {
tableView.reloadData()
}
}
Найдите и исправьте ошибку.
main.sync блокирует вызывающий поток, пока блок не выполнится на главной очереди. Но вызывающий и есть главный поток, он заблокирован, поэтому блок не выполняется — взаимоблокировка. Исправление — если уже на главном, выполните напрямую; иначе main.async.
- ✗Считают главную очередь параллельной, способной войти в себя
- ✗Винят
reloadData(), а не синхронный диспатч на главную очередь - ✗Оставляют
main.sync, лишь прикрывая его проверкой потока
- →Почему
main.asyncизбегает взаимоблокировки, которую даёт здесьmain.sync? - →Когда вызов
syncс главного потока на другую очередь безопасен?
Причина — main.sync с главного потока: поток блокируется в ожидании, пока блок выполнится на главной очереди, но выполнить его некому — тот же поток заблокирован.
func reloadOnMain() {
if Thread.isMainThread {
tableView.reloadData() // уже на главном — просто выполняем
} else {
DispatchQueue.main.async { // с фона — асинхронно на главную
self.tableView.reloadData()
}
}
}
Никогда не вызывайте main.sync из кода, который может уже работать на главном потоке.