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

时间:2017-03-13 20:33:10

标签: swift grand-central-dispatch

在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?

3 个答案:

答案 0 :(得分:15)

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,async可能足够好并且更安全以避免死锁。除非是特殊情况,您需要等到主要完成后再继续执行异步任务才能完成。

至于崩溃的示例 - 调用同步和定位当前队列是死锁(调用队列等待同步块完成,但是它没有启动,因为目标队列(相同)正忙着等待sync呼吁完成)这可能是崩溃的原因。

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

答案 1 :(得分:1)

队列

GCD提供了三种主要的队列类型:

1。主队列:在主线程上运行,是一个串行队列
2。全局队列:由整个系统共享的并发队列。有四个这样的队列,它们具有不同的优先级:高,默认,低和后台。后台优先级队列的优先级最低,并且在任何I / O活动中都会对其进行限制,以最大程度地减少对系统的负面影响。
3。自定义队列:您创建的队列可以是串行的或并发的。这些队列中的请求实际上最终位于全局队列之一中。

同步与异步

使用GCD,您可以分派synchronouslyasynchronously的任务。

任务完成后,synchronous函数将控制权返回给调用者。您可以通过调用DispatchQueue.sync(execute:)来同步安排工作单元。

asynchronous函数立即返回,命令任务开始但不等待其完成。因此,异步功能不会阻止当前执行线程继续进行下一个功能。您可以通过调用DispatchQueue.async(execute:)异步安排工作单元。

摘要

通常,当您需要在后台执行基于网络或CPU密集型任务而又不阻塞当前线程时,您想使用async

以下是如何和何时在async中使用各种队列的快速指南:

  • 主队列::这是在并发队列上完成任务中的工作后更新UI的常见选择。为此,您需要在另一个内编写一个闭包。定位主队列并调用async可确保此新任务将在当前方法完成后的某个时间执行。
  • 全局队列:这是在后台执行非UI工作的常见选择。
  • 自定义串行队列:当您要串行执行后台工作并对其进行跟踪时,这是一个不错的选择。由于您一次只知道一个任务正在执行,因此消除了资源争用和争用条件。请注意,如果您需要方法中的数据,则必须声明另一个闭包来检索它,或考虑使用sync

常见错误:

DispatchQueue.main.sync队列中调用main,由于调用队列(main)将等待直到分派的块完成,但它(分派的块)才被冻结,因此应用将被冻结)甚至无法启动(因为main队列已停止并正在等待)

了解更多here

答案 2 :(得分:0)

DispatchQueue.<queue>.<sync/async>说在<sync/async>上运行<queue>任务。

<queue> [About]
Main是一个串行队列,通常用于更新UI
Global是并发队列,通常用于进行其他计算以卸载主队列。

<sync/async> [About]
Sync-阻止当前线程,并等待它在特定队列上完成
Async-不要阻塞当前线程,不要将执行代码块发送到特定队列

常见错误:

DispatchQueue.main.sync队列中调用main,由于调用队列(main)将等待直到分派的块完成,但它(分派的块)才被冻结,因此应用将被冻结)甚至无法启动(因为main队列已停止并正在等待)