DispatchQueue.main.sync 与 DispatchQueue.main.sync 的区别

我已经使用 DispatchQueue.main.async很长时间来执行 UI 相关的操作。

Swift 同时提供 DispatchQueue.main.asyncDispatchQueue.main.sync,并且都在主队列上执行。

有人能告诉我它们之间的区别吗? 我应该什么时候使用它们?

DispatchQueue.main.async {
self.imageView.image = imageView
self.lbltitle.text = ""


}


DispatchQueue.main.sync {
self.imageView.image = imageView
self.lbltitle.text = ""
}
126908 次浏览

为什么是并发?

一旦你给你的应用程序添加繁重的任务,比如数据加载,它就会降低你的 UI 工作速度,甚至冻结它。 并发允许您“同时”执行2个或多个任务。 这种方法的缺点是线程安全性,并不总是容易控制。当不同的任务想要访问相同的资源时,比如试图在不同的线程上更改相同的变量,或者访问已经被不同的线程阻塞的资源。

我们需要注意一些抽象概念。

  • 排队。
  • 同步/异步任务性能。
  • 优先级。
  • 常见问题

排队

必须是 连环杀手同时。以及 全球性的二等兵在同一时间。

对于串行队列,任务将逐个完成,而对于并发队列,任务将同时执行,并在意外的时间表上完成。与并发队列相比,同一组任务在串行队列上花费的时间更多。

您可以创建自己的 私人排队(连环杀手同时)或使用已经可用的 全局(系统)队列主队是所有 全球队列中唯一的 串行队列

强烈建议不要在 主队上执行与 UI 工作无关的繁重任务(比如从网络加载数据) ,而是在其他队列上执行这些任务,以保持 UI 解冻并响应用户操作。如果我们允许在其他队列上更改 UI,则可以按照不同的、意想不到的计划和速度进行更改。一些 UI 元素可以在需要之前或之后绘制。它会破坏用户界面。我们还需要记住,因为 全球队列系统队列,所以系统可以在它们上面运行一些其他任务。

服务质素/优先次序

队列还有不同的 服务质量,它设置执行 优先权的任务(从最高到最低) :
.UserInteractive -至于 主队 < br/> 。用户启动-对于用户发起的任务,用户需要等待一些响应 < br/> 。效用-对于需要一些时间而且不需要立即响应的任务,例如处理数据 < br/> 。背景-对于与可视部分无关的任务,对于完成时间不严格)。< br/> < br/> 还有 < br/> < br/> 。默认队列不传输 服务质量信息。 如果不可能检测到 服务质量服务质量将在 。用户启动。效用之间使用。

任务可以执行 同步异步的

  • 同步 函数仅在任务完成后才将控制返回给当前队列。它阻塞队列并等待任务完成。

  • 异步 函数在将任务发送到不同队列上执行之后立即将控制返回给当前队列。它不会等到任务完成。它不会阻塞队列。

常见问题。

程序员在设计并发应用程序时最常犯的错误如下:

  • 竞争条件 -当应用程序工作取决于代码部件执行的顺序时引起。
  • 优先转置 -当较高优先级的任务由于某些资源被阻塞而等待较小优先级的任务完成时
  • Deadlock -当一些队列具有无限等待已被这些队列阻塞的源(变量、数据等)时。

永远不要调用主队列上的 sync 函数
如果你在主队列上调用 sync 函数,它会阻塞队列,队列也会等待任务完成,但是任务永远不会完成,因为由于队列已经被阻塞,它甚至不能启动。它叫做 僵局

何时使用同步? 当我们需要等待,直到任务完成。当我们确保某个函数/方法不被双重调用时。我们有同步,并试图防止它被双重调用,直到它完全完成。下面是解决这个问题的一些代码: < br/> 如何找出是什么导致 IOS 设备崩溃报告错误?

当您使用 async时,它允许调用队列继续前进,而不必等待直到分派块被执行。相反,sync将使调用队列停止并等待,直到您在块中分派的工作完成。因此 sync容易导致死锁。尝试从主队列运行 DispatchQueue.main.sync,应用程序会冻结,因为调用队列将等待,直到分派块结束,但它甚至不能启动(因为队列已停止和等待)

什么时候使用 sync?当您需要等待在 DIFFERENT 队列上完成某些操作,然后才继续处理当前队列时

使用 sync 的示例:

在串行队列中,可以使用 sync作为互斥锁,以确保只有一个线程能够同时执行受保护的代码段。

syncasync方法对调用它们的队列没有影响。

sync将阻塞所调用的线程 来自,而不是所调用的队列 开始DispatchQueue的属性决定了 DispatchQueue是等待任务执行(串行队列)还是在当前任务完成(并发队列)之前运行下一个任务。

因此,即使 DispatchQueue.main.async是一个异步调用,添加到其中的重型操作也可以冻结 UI,因为它的操作是在主线程上串行执行的。如果从后台线程调用此方法,即使 UI 似乎被冻结,控制也会立即返回到该线程。这是因为 async调用是在 DispatchQueue.main上进行的

GCD允许您执行任务 synchronouslyasynchronously< sup > [ About ]

函数返回任务完成时的控件

asynchronous(分派和进行)函数立即返回一个控件,将任务分派到适当的队列中启动,但不等待任务完成。

[ DispatchQueue ]