main.async против main.sync() против global().async в Swift3 GCD
Пример A:- Это вызывает App Crash.
DispatchQueue.main.async {
let url = URL(string: imageUrl)
do {
let data = try Data(contentsOf: url!)
DispatchQueue.main.sync {
self.imageIcon.image = UIImage(data: data)
}
}
Пример Б: - Но это не так
DispatchQueue.global().async {
let url = URL(string: imageUrl)
do {
let data = try Data(contentsOf: url!)
DispatchQueue.main.sync {
self.imageIcon.image = UIImage(data: data)
}
}
Насколько мне известно,
- x.sync означает выполнение действий в основном потоке / потоке пользовательского интерфейса, а x.async означает выполнение действий в фоновом потоке.
- Глобальный означает выполнение чего-либо с параллельной очередью, т.е. параллельное задание.
Quest1: - Так почему мое приложение зависло, когда я выполнил задачу в фоновом потоке, т.е. main.async, а затем вызвал основной поток для обновления пользовательского интерфейса.
Quest2: - Есть ли разница в main.async & global(). Async.
3 ответа
Проще говоря, я прихожу к выводу, что -
- Очередь - существует 3 типа очереди, т.е. 1 основная очередь, 4 глобальные очереди и любое количество пользовательских очередей.
- Потоки - One is Main Thread и другие фоновые потоки, которые нам предоставляет система.
DispatchQueue.main.async
-Это означает выполнение задачи в основной очереди с использованием фонового потока (без блокировки пользовательского интерфейса), и когда задача автоматически завершает ее Обновление до пользовательского интерфейса, поскольку оно уже находится в главной очереди.
DispatchQueue.global (). Async вместе с global (). Sync
Это означает выполнение задачи в глобальной очереди с использованием фонового потока, а когда задача завершается, чем использование global (). Sync переносит работу из globalQueue в mainQueue, которая обновляется до пользовательского интерфейса.
Причина сбоя моего приложения
Я пытался перенести завершенную задачу в Main Queue с помощью (main.sync), но он уже был в Main Queue, потому что я не переключил очередь, и это создает DeadLock (Main Queue, ожидающий себя), вызывает сбой моего приложения
Grand Central Dispatch
GCD
работает в диспетчерских очередях DispatchQueue
с порядком FIFO
DispatchQueue.<queue>.<sync/async>
означает запустить <sync/async>
задача по <queue>
очередь
main
- последовательная очередь в основном потоке, которая используется для работы с UI
DispatchQueue.main
global()
- параллельная очередь, разделяемая системой.global()
метод передачи приоритета в задаче с использованием qos
QoSClass
(priority
GlobalQueuePriority
устарела): background
, default
, unspecified
, userInitiated
, userInteractive
, utility
DispatchQueue.global()
DispatchQueue.global(qos: .background)
Пользовательская очередь: - serial
или concurrent
настраиваемая очередь
DispatchQueue(label: "serialQueue")
DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
синхронизация / асинхронность
sync
- заблокировать текущий поток и ждать, когда он будет завершен в указанной очереди
async
- не блокировать текущий поток и отправлять блок выполнения кода в указанную очередь
Общая ошибка:
Если вы позвоните DispatchQueue.main.sync
на main
thread - приложение будет заморожено, потому что вызывающий DispatchQueue.main.sync
начинает ожидание сразу после завершения отправленного блока (отправленный блок не запускается)
В первом случае вы запускаете код на main
а затем вы используете main.sync
в основной теме. По сути, вы пытаетесь рассказать main
очередь ждать себя - что, очевидно, чепуха и, следовательно, вызывает сбой.
Во втором случае вы запускаете код в фоновом потоке, а затем используете main.sync
ждать, пока main
поток может запустить блок, предоставленный в main.sync
,
В общем, я бы использовал async
и не sync
все время, если только sync
необходимо - и всегда синхронизировать один поток (DispatchQueue
) с другим, никогда с тем же.
Вы смешивали термины sync/async и main/global.
Синхронизация - синхронное выполнение некоторой задачи (т. Е. Поток, который может быть основным / глобальным / любым другим потоком, будет ожидать завершения задачи)
Async - запускать некоторую задачу асинхронно (то есть поток, который может быть основным / глобальным / любым другим потоком, поместит задачу в очередь и продолжит выполнение следующих шагов за пределами вашего блока. Он не будет ждать)
Теперь давайте пошли один за другим в коде, который вылетал:
Давайте назовем несколько имен для наших тем, чтобы нам было легко их понять:
1) ThreadA - который встречает ваши операторы отправки (это также может быть основной поток, но для целей объяснения я чувствую себя лучше)
2) ThreadB - глобальный поток, который создается при отправке какого-либо задания.
3) ThreadMain - Основная тема
Пример А:
DispatchQueue.main.async - ThreadA приходит и выполняет этот оператор, помещает ваш блок в ThreadMain и переходит (с момента его асинхронности) к следующим шагам после блока.
Теперь давайте поговорим о ThreadMain, что он будет делать здесь. Так как ThreadMain получил блок (представленный ThreadA), он начинает выполнять шаг за шагом, и внезапно он видит "DispatchQueue.main.sync" и отправляет внутренний блок в ту же очередь TheradMain и сохраняет onnnnn waitggggg (начиная с его синхронизации). Так что буквально вы превращаете ThreadMain в тупиковую ситуацию.