iOS RunLoop 和 DispatchQueue.main.async

iOS RunLoop and DispatchQueue.main.async

为什么 print("2") 部分在下面的代码中永远不会被调用? 我认为内部 main.async 会将块推入主循环的队列中, 然后 RunLoop.run 会执行它,但显然情况并非如此。 (打印 1runrunrun 等)

此外,如果我删除外部 main.async,直接 运行 该块中的代码 (仍在主队列中,在新的单视图应用程序的 viewDidLoad 中), 然后内部 main.async 块确实得到执行(打印 1run2)。 为什么这一变化会产生如此大的不同?

var x = -1
DispatchQueue.main.async {   //  comment out this line for question #2
    print("1")
    x = 1
    DispatchQueue.main.async {
        print("2")
        x = 2
    }
    while x == 1 {
        print("run")
        RunLoop.main.run(mode: .default, before: Date() + 1)
    }
}   //  comment out this line for question #2

在您的第一个示例中,第一个 async 阻塞 main 串行队列,直到它 returns 来自外部 async 调用,而这不会发生x1。内部 GCD async 任务(将 x 更新为 2)将永远没有机会 运行 因为串行 GCD 队列现在在 while 中被阻塞环形。在主 运行 循环中尝试 run 并不能绕过 GCD 串行队列的 rules/behavior。它只会耗尽已添加到其中的 运行 事件循环。

在你的第二个例子中,你没有阻塞 GCD main 队列,所以当你点击 run 时,调度块将 x 更新为 2确实有机会运行,让它继续。

底线,不要混淆 GCD 主队列和主 运行 循环。是的,它们都使用主线程,但是运行循环不能用来规避串行GCD队列的行为。