[英]Difference between DispatchQueue.main.async and DispatchQueue.main.sync
I have been using DispatchQueue.main.async
for a long time to perform UI related operations.我一直在使用
DispatchQueue.main.async
进行 UI 相关操作。
Swift provides both DispatchQueue.main.async
and DispatchQueue.main.sync
, and both are performed on the main queue. Swift 提供了
DispatchQueue.main.async
和DispatchQueue.main.sync
,并且都在主队列上执行。
Can anyone tell me the difference between them?谁能告诉我它们之间的区别? When should I use each?
我应该什么时候使用?
DispatchQueue.main.async {
self.imageView.image = imageView
self.lbltitle.text = ""
}
DispatchQueue.main.sync {
self.imageView.image = imageView
self.lbltitle.text = ""
}
As soon as you add heavy tasks to your app like data loading it slows your UI work down or even freezes it.一旦您向应用程序添加繁重的任务(例如数据加载),它就会减慢您的 UI 工作速度,甚至冻结它。 Concurrency lets you perform 2 or more tasks “simultaneously”.
并发使您可以“同时”执行 2 个或更多任务。 The disadvantage of this approach is that thread safety which is not always as easy to control.
这种方法的缺点是线程安全性并不总是那么容易控制。 Fe when different tasks want to access the same resources like trying to change the same variable on a different threads or accessing the resources already blocked by the different threads.
Fe 当不同的任务想要访问相同的资源时,例如尝试更改不同线程上的相同变量或访问已被不同线程阻塞的资源。
There are a few abstractions we need to be aware of.我们需要注意一些抽象。
Must be serial or concurrent .必须是串行的或并发的。 As well as global or private at the same time.
以及同时全局或私有。
With serial queues, tasks will be finished one by one while with concurrent queues, tasks will be performed simultaneously and will be finished on unexpected schedules.在串行队列中,任务将一个一个地完成,而在并发队列中,任务将同时执行并按意外的时间表完成。 The same group of tasks will take the way more time on a serial queue compared to a concurrent queue.
与并发队列相比,同一组任务在串行队列上花费的时间更多。
You can create your own private queues (both serial or concurrent ) or use already available global (system) queues .您可以创建自己的专用队列(串行或并发)或使用已经可用的全局(系统)队列。 The main queue is the only serial queue out of all of the global queues .
主队列是所有全局队列中唯一的串行队列。
It is highly recommended to not perform heavy tasks which are not referred to UI work on the main queue (fe loading data from the network), but instead to do them on the other queues to keep the UI unfrozen and responsive to the user actions.强烈建议不要在主队列上执行与 UI 工作无关的繁重任务(从网络加载数据),而是在其他队列上执行这些任务,以保持 UI 不冻结并响应用户操作。 If we let the UI be changed on the other queues, the changes can be made on a different and unexpected schedule and speed.
如果我们让其他队列上的 UI 更改,则可以以不同且意外的时间表和速度进行更改。 Some UI elements can be drawn before or after they are needed.
一些 UI 元素可以在需要之前或之后绘制。 It can crash the UI.
它可能会导致用户界面崩溃。 We also need to keep in mind that since the global queues are system queues there are some other tasks can run by the system on them.
我们还需要记住,由于全局队列是系统队列,因此系统可以在它们上运行一些其他任务。
Queues also have different qos (Quality of Service) which sets the task performing priority (from highest to lowest here):队列也有不同的qos(服务质量) ,它设置任务执行优先级(从高到低):
.userInteractive - main queue .userInteractive -主队列
.userInitiated - for the user initiated tasks on which user waits for some response .userInitiated - 用于用户启动的任务,用户等待某些响应
.utility - for the tasks which takes some time and doesn't require immediate response, eg working with data .utility - 用于需要一些时间且不需要立即响应的任务,例如处理数据
.background - for the tasks which aren't related with the visual part and which aren't strict for the completion time). .background - 用于与视觉部分无关且对完成时间不严格的任务)。
There is also还有
.default queue which does't transfer the qos information. .default队列,不传输qos信息。 If it wasn't possible to detect the qos the qos will be used between .userInitiated and .utility .
如果无法检测到qos ,则将在.userInitiated和.utility之间使用qos 。
Tasks can be performed synchronously or asynchronously .任务可以同步或异步执行。
Synchronous function returns control to the current queue only after the task is finished.同步函数只有在任务完成后才将控制权返回到当前队列。 It blocks the queue and waits until the task is finished.
它阻塞队列并等待任务完成。
Asynchronous function returns control to the current queue right after task has been sent to be performed on the different queue.异步函数在发送任务后立即将控制权返回到当前队列以在不同队列上执行。 It doesn't wait until the task is finished.
它不会等到任务完成。 It doesn't block the queue.
它不会阻塞队列。
The most popular mistakes programmers make while projecting the concurrent apps are the following:程序员在预测并发应用程序时最常犯的错误如下:
NEVER call the sync function on the main queue .永远不要在主队列上调用同步函数。
If you call the sync function on the main queue it will block the queue as well as the queue will be waiting for the task to be completed but the task will never be finished since it will not be even able to start due to the queue is already blocked.如果您在主队列上调用同步函数,它将阻塞队列,队列将等待任务完成但任务永远不会完成,因为它甚至无法启动,因为队列是已经屏蔽了。 It is called deadlock .
它被称为死锁。
When to use sync?什么时候使用同步? When we need to wait until the task is finished.
当我们需要等到任务完成时。 Fe when we are making sure that some function/method is not double called.
Fe,当我们确保某些函数/方法不被重复调用时。 Fe we have synchronization and trying to prevent it to be double called until it's completely finished.
Fe 我们有同步并试图防止它被双重调用,直到它完全完成。 Here's some code for this concern:
这是针对此问题的一些代码:
How to find out what caused error crash report on IOS device? 如何找出是什么导致了 IOS 设备上的错误崩溃报告?
When you use async
it lets the calling queue move on without waiting until the dispatched block is executed.当您使用
async
它可以让调用队列继续移动,而无需等到执行分派的块。 On the contrary sync
will make the calling queue stop and wait until the work you've dispatched in the block is done.相反,
sync
将使调用队列停止并等待您在块中分派的工作完成。 Therefore sync
is subject to lead to deadlocks.因此
sync
容易导致死锁。 Try running DispatchQueue.main.sync
from the main queue and the app will freeze because the calling queue will wait until the dispatched block is over but it won't be even able to start (because the queue is stopped and waiting)尝试从主队列运行
DispatchQueue.main.sync
并且应用程序将冻结,因为调用队列将等到调度块结束但它甚至无法启动(因为队列已停止并等待)
When to use sync
?什么时候使用
sync
? When you need to wait for something done on a DIFFERENT queue and only then continue working on your current queue当您需要等待在 DIFFERENT 队列上完成某事,然后才继续处理当前队列时
Example of using sync:使用同步的示例:
On a serial queue you could use sync
as a mutex in order to make sure that only one thread is able to perform the protected piece of code at the same time.在串行队列上,您可以将
sync
用作互斥锁,以确保只有一个线程能够同时执行受保护的代码段。
GCD
allows you to execute a task synchronously
or asynchronously
[About] GCD
允许您synchronously
或asynchronously
执行任务[关于]
synchronous
(block and wait) function returns a control when the task will be completed synchronous
(阻塞和等待)函数在任务完成时返回控制
asynchronous
(dispatch and proceed) function returns a control immediately, dispatching the task to start to an appropriate queue but not waiting for it to complete. asynchronous
(分派和继续)函数立即返回一个控制,分派任务以开始到适当的队列但不等待它完成。
sync
or async
methods have no effect on the queue on which they are called. sync
或async
方法对调用它们的队列没有影响。
sync
will block the thread from which it is called and not the queue on which it is called. sync
将阻止从其中它被称为并且它们不是在它被称为队列中的线程。 It is the property of DispatchQueue
which decides whether the DispatchQueue
will wait for the task execution (serial queue) or can run the next task before current task gets finished (concurrent queue). DispatchQueue
的属性决定了DispatchQueue
等待任务执行(串行队列)还是可以在当前任务完成之前运行下一个任务(并发队列)。
So even when DispatchQueue.main.async
is an async call, a heavy duty operation added in it can freeze the UI as its operations are serially executed on the main thread.因此,即使
DispatchQueue.main.async
是异步调用,添加到其中的重型操作也会冻结 UI,因为其操作是在主线程上串行执行的。 If this method is called from the background thread, control will return to that thread instantaneously even when UI seems to be frozen.如果从后台线程调用此方法,即使 UI 似乎被冻结,控制权也会立即返回该线程。 This is because
async
call is made on DispatchQueue.main
这是因为
async
调用是在DispatchQueue.main
// Main Thread
DispatchQueue.global(qos: .userInteractive).sync {
self.tableView.reloadData()
}
//Thread 4 Queue : com.apple.root.user-interactive-qos (concurrent)
DispatchQueue.global(qos: .userInteractive).async {
// Can't do UI Stuff here
self.tableView.reloadData()
}
.userInteractive
for qos makes you have two options about the thread, Either you get the main thread or get a background thread. .userInteractive
可以使您对线程有两个选择,要么获取主线程,要么获取后台线程。 It depends on how you are going to perform thread synchronously or asynchronously.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.