Почему мы используем async в главном потоке - PullRequest
1 голос
/ 09 апреля 2019

Обновление пользовательского интерфейса в потоке, отличном от основного, является распространенной ошибкой, которая может привести к пропущенным обновлениям пользовательского интерфейса, визуальным дефектам, повреждению данных и сбоям.

https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Пример:

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
   if let data = data {
      DispatchQueue.main.async { // Correct
         self.label.text = "\(data.count) bytes downloaded"
      }
   }
}
task.resume()

Мой вопрос начинается здесь - Меня смущает вышеприведенное утверждение, когда мы говорим .async означает не одновременно (или не параллельно) с .main. Может кто-нибудь объяснить мою проблему?

Ответы [ 2 ]

4 голосов
/ 09 апреля 2019

DispatchQueue.main.async означает, что вы ставите задачу в очередь в основной очереди, не дожидаясь ее выполнения.Задачи основной очереди будут автоматически запускаться в главном потоке по расписанию ОС.

Думайте о каждом DispatchQueue как о работнике.Вызов .async добавляет задачу в список TODO работника и не ждет, пока работник завершит задачу.DispathQueue.main - это конкретный рабочий, который работает в главном потоке.

С другой стороны, .sync будет блокировать поток до тех пор, пока не завершится выполнение блока задач.Вы можете вызвать .sync в любом потоке, кроме основного, так как основной поток не должен быть заблокирован.

Это не значит, что вы не можете позвонить DispatchQueue.main.sync.Вы можете вызвать DispatchQueue.main.sync точно так же, как любой пользовательский dispathQueue.sync в неосновном потоке.

Например,

DispatchQueue(label: "bgqueue", qos: .background).async
{ 
    DispatchQueue.main.sync{} 
} 

в порядке.

Но

DispatchQueue.main.async{ 
    DispatchQueue.main.sync{} 
} 

- это НЕ.

.sync обычно не совсем полезно.Если вы хотите, чтобы что-то произошло после основной задачи очереди, вы просто помещаете это «что-то» в главную очередь.Не стоит блокировать поток, если не нужно.

При этом необходимо помнить два правила при использовании .sync независимо от того, какая очередь получает вызов .sync:

  1. никогда не вызывать .sync изочередь к себе, что вызывает тупик.
  2. никогда не вызывать .sync из основной очереди, что блокирует поток пользовательского интерфейса.
2 голосов
/ 09 апреля 2019

Я думаю, вы не понимаете, как работает DispatchQueue.

DispatchQueue просто управляет пулом потоков, а когда мы даем ему блок кода для выполнения, он просто выбирает свободный поток и запускает этот фрагменткод на нем.

Таким образом, в основном один поток может использоваться многими очередями.Очередь - это просто список задач, который управляет всеми задачами, которые будут выполняться в будущем.

Таким образом, в основном здесь, когда вы выполняете DispatchQueue.main.async, тогда вы просто указываете main queue выполнить ваш код, не ожидая ожиданиявыполнение заданий.

...