一尘不染

global()。async中的main.sync是什么意思?

swift

在Swift中,有时会使用这种模式。

DispatchQueue.global().async {
    // do stuff in background, concurrent thread

    DispatchQueue.main.sync {
        // update UI
    }
}

这种模式的目的很明确。在全局线程中执行耗时的计算,以使UI不会被锁定,并在计算完成后更新主线程中的UI。

如果没有什么要计算怎么办?我刚刚在我的项目中发现了一个逻辑

//A
DispatchQueue.main.sync {
    // do something
}

崩溃但

// B
DispatchQueue.global().async {
    DispatchQueue.main.sync {
        // do something
    }
}

不会崩溃。

它们有何不同?情况 B 与此不同吗?

// C
DispatchQueue.main.async {
    // do something
}

还有一个问题。我知道主线程是串行队列,但是如果我在多个线程中运行多个代码块main.async,它的工作方式就像并发队列。

DispatchQueue.main.async {
    // do A
}

DispatchQueue.main.async {
    // do B
}

如果主线程确实是一个串行队列,那么它们如何同时运行?如果只是时间片,那么它们与全局并发队列有什么不同,除了主线程可以更新UI之外?


阅读 387

收藏
2020-07-07

共1个答案

一尘不染

x.sync表示调用队列将暂停并等待,直到同步块结束才能继续。因此在您的示例中:

DispatchQueue.global().async {
    // yada yada something
    DispatchQueue.main.sync {
        // update UI
    }
    // this will happen only after 'update UI' has finished executing
}

通常,您不需要sync回到主线程,异步可能足够好并且更安全,可以避免死锁。除非是特殊情况,否则您需要等到main完成后再继续执行异步任务。

至于一个崩溃的例子-
调用同步并以当前队列为目标是一个死锁(调用队列等待同步块完成,但由于目标队列(相同)正忙于等待sync调用而无法启动),这可能是为什么迷恋;撞车;崩溃。

至于使用异步在主队列上调度多个块:它们不会并行运行-
它们将一个接一个地发生。也不要假设队列==线程。将多个块调度到同一队列中,可能会创建系统允许的尽可能多的线程。只是主队列是利用主线程的特殊之处。

2020-07-07