iOS RunLoop 和 DispatchQueue.main.async

imr*_*mre 2 nsrunloop ios dispatch-queue

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

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

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
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 5

在您的第一个示例中,第一个块async会阻塞main串行队列,直到它从外部async调用返回,这在xis时不会发生\xe2\x80\x99t 1。内部 GCDasync任务(更新x2)将永远没有机会运行,因为串行 GCD 队列现在在该while循环中被阻塞。在主运行循环上的尝试run不会规避 GCD 串行队列的规则/行为。它只会耗尽已添加到其中的事件的运行循环。

\n

在第二个示例中,您还没有\xe2\x80\x99t 阻止了GCDmain队列,因此当您点击 时run,更新到的分派块x确实2有机会运行,让它继续进行。

\n

最重要的是,不要将 GCD 主队列和主运行循环混为一谈。是的,它们都使用主线程,但是运行循环不能用于规避串行 GCD 队列的行为。

\n