IOS - Разница между DispatchQueue.main.asyncAfter (deadline: .now ()) и выполняется (_: with: afterDelay :) с задержкой 0 - PullRequest
0 голосов
/ 04 сентября 2018

Я понял, что есть разница между использованием DispatchQueue.main.asyncAfter(deadline: .now()) и perform(_:with:afterDelay:0), когда основная очередь занята.

Обратите внимание, что perform(_:with:afterDelay:) вызывается из основной очереди в моей ситуации.

Похоже, DispatchQueue.main.asyncAfter(deadline: .now()) выполняет задачу немедленно в следующем цикле выполнения, не заботясь о главной очереди, но perform(_:with:afterDelay:) с задержкой 0 будет ожидать и выполнять задачу только тогда, когда основная очередь «свободна» (возможно, это не будет вызывается при следующем цикле выполнения).

Согласно документу Apple для выполнить (_: with: afterDelay:)

Задание задержки 0 не обязательно приводит к немедленному выполнению селектора. Селектор все еще находится в очереди в цикле выполнения потока и выполняется как можно скорее.

Я не уверен, что понимаю их правильно, поэтому кто-нибудь может мне помочь объяснить, в чем разница между ними? Что означает выполнено как можно скорее означает?

Я нашел такой же вопрос здесь , но похоже, что это не то, что я хочу.

1 Ответ

0 голосов
/ 04 сентября 2018

Я создал этот автономный тест для изучения этой темы.

class ViewController: UIViewController {

    @objc func test1(_ info: Any) {
        guard let str = info as? String else { return }
        sleep(1)
        print(str)

        if str != "selector 3" {
            self.perform(#selector(test1), with: "selector 3", afterDelay: 0)
        }

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            sleep(1)
            print("dispatch 4 queued by \(str)")
        }

    }


    @IBAction func test(_ sender: UIButton) {
        print("begin test")

        self.perform(#selector(test1), with: "selector 1", afterDelay: 0)

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            DispatchQueue.main.asyncAfter(deadline: .now()) {
                sleep(1)
                print("dispatch 3")
            }
            sleep(1)
            print("dispatch 1")
        }

        self.perform(#selector(test1), with: "selector 2", afterDelay: 0)

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            sleep(1)
            print("dispatch 2")
        }

        print("end test")
    }

}

Результирующий вывод:

begin test
end test
dispatch 1
dispatch 2
selector 1
selector 2
dispatch 3
dispatch 4 queued by selector 1
dispatch 4 queued by selector 2
selector 3
selector 3
dispatch 4 queued by selector 3
dispatch 4 queued by selector 3

На что обратить внимание:

  1. begin test и end test печатают перед любым другим выводом, показывая, что и perform(_:with:afterDelay:), и DispatchQueue.main.asyncAfter поставлены в очередь и запускаются позже.
  2. Первые два DispatchQueue запускаются до perform, даже если они находятся в очереди в другом порядке.
  3. Все распечатки выполняются с интервалом в одну секунду, что означает, что все они выполняются в одной и той же очереди в ожидании завершения предыдущего.
  4. dispatch 3 не опережает selector 1 и selector 2, даже если он стоит в очереди до печати dispatch 1.

Выводы:

  1. Оба Dispatch.main.asyncAfter и perform(_:with:afterDelay:) ставят в очередь свой селектор / замыкание, которое будет выполнено позже. Поскольку вы запускаете perform(_:with:afterDelay:) в главном потоке, он использует основную очередь для своего планирования.
  2. По какой-то неизвестной (для меня) причине Dispatch.main.asyncAfter(0) вызовы ставятся в очередь до perform(_:with:afterDelay:0) вызовов в очереди в том же цикле выполнения. Примечание: если к Dispatch.main.asyncAfter добавится какая-либо задержка, она будет поставлена ​​в очередь после perform(_:with:afterDelay:). Попробуйте использовать .now() + .milliseconds(1), например.
  3. выполняется как можно скорее - это просто еще один способ сказать, что они поставлены в очередь и обрабатываются в порядке очереди. В зависимости от того, сколько времени задачи ожидают в очереди, может пройти много циклов выполнения, прежде чем задача будет окончательно обработана.
...