ios DispatchQueue.main.async 和 DispatchQueue.main.sync 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44324595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between DispatchQueue.main.async and DispatchQueue.main.sync
提问by Aman.Samghani
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 = ""
}
采纳答案by Andrey Chernukha
When you use async
it lets the calling queue move on without waiting until the dispatched block is executed. On the contrary sync
will make the calling queue stop and wait until the work you've dispatched in the block is done. Therefore sync
is subject to lead to deadlocks. 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)
当您使用async
它时,可以让调用队列继续前进,而无需等到分派的块被执行。相反sync
将使调用队列停止并等待您在块中分派的工作完成。因此sync
很容易导致死锁。尝试DispatchQueue.main.sync
从主队列运行,应用程序将冻结,因为调用队列将等待调度块结束,但它甚至无法启动(因为队列已停止并等待)
When to use sync
? When you need to wait for something done on a DIFFERENT queue and only then continue working on your current queue
什么时候使用sync
?当您需要等待在 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
用作互斥锁,以确保只有一个线程能够同时执行受保护的代码段。
回答by Alexander
Why Concurrency?
为什么要并发?
As soon as you add heavy tasks to your app like data loading it slows your UI work down or even freezes it. Concurrency lets you perform 2 or more tasks “simultaneously”. The disadvantage of this approach is that thread safety which is not always as easy to control. F.e. 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.
一旦您向应用程序添加繁重的任务(例如数据加载),它就会减慢您的 UI 工作速度,甚至冻结它。并发使您可以“同时”执行 2 个或更多任务。这种方法的缺点是线程安全性并不总是那么容易控制。Fe 当不同的任务想要访问相同的资源时,例如尝试更改不同线程上的相同变量或访问已被不同线程阻塞的资源。
There are a few abstractions we need to be aware of.
我们需要注意一些抽象。
- Queues.
- Synchronous/Asynchronous task performance.
- Priorities.
- Common troubles.
- 队列。
- 同步/异步任务性能。
- 优先事项。
- 常见的烦恼。
Queues
队列
Must be serialor concurrent. As well as globalor privateat 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 serialor concurrent) or use already available global (system) queues. The main queueis the only serial queueout 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(f.e. 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. If we let the UI be changed on the other queues, the changes can be made on a different and unexpected schedule and speed. Some UI elements can be drawn before or after they are needed. It can crash the UI. We also need to keep in mind that since the global queuesare system queuesthere are some other tasks can run by the system on them.
强烈建议不要在主队列上执行与 UI 工作无关的繁重任务(从网络加载数据),而是在其他队列上执行这些任务,以保持 UI 不冻结并响应用户操作。如果我们让其他队列上的 UI 更改,则可以以不同且意外的时间表和速度进行更改。一些 UI 元素可以在需要之前或之后绘制。它可能会导致用户界面崩溃。我们还需要记住,由于全局队列是系统队列,因此系统可以在它们上运行一些其他任务。
Quality of Service / Priority
服务质量/优先级
Queues also have different qos (Quality of Service)which sets the task performing priority(from highest to lowest here):
.userInteractive- main queue
.userInitiated- for the user initiated tasks on which user waits for some response
.utility- for the tasks which takes some time and doesn't require immediate response, e.g working with data
.background- for the tasks which aren't related with the visual part and which aren't strict for the completion time).
There is also
.defaultqueue which does't transfer the qosinformation.
If it wasn't possible to detect the qosthe qoswill be used between .userInitiatedand .utility.
队列也有不同的qos(服务质量),它设置任务执行优先级(这里从最高到最低):
.userInteractive-主队列
.userInitiated- 用于用户启动的任务,用户等待一些响应
.utility- 用于任务这需要一些时间并且不需要立即响应,例如使用数据
.background- 对于与视觉部分无关且对完成时间不严格的任务)。
还有不传输qos信息的
.default队列。如果这是不可能检测到的QoS的qos将用于.userInitiated和.utility之间。
Tasks can be performed synchronouslyor asynchronously.
任务可以同步或异步执行。
Synchronousfunction returns control to the current queue only after the task is finished. It blocks the queue and waits until the task is finished.
Asynchronousfunction 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.
同步函数只有在任务完成后才将控制权返回到当前队列。它阻塞队列并等待任务完成。
异步函数在发送任务后立即将控制权返回到当前队列以在不同队列上执行。它不会等到任务完成。它不会阻塞队列。
Common Troubles.
常见问题。
The most popular mistakes programmers make while projecting the concurrent apps are the following:
程序员在预测并发应用程序时最常犯的错误如下:
- Race condition- caused when the app work depends on the order of the code parts execution.
- Priority inversion- when the higher priority tasks wait for the smaller priority tasks to be finished due to some resources being blocked
- Deadlock- when a few queues have infinite wait for the sources (variables, data etc.) already blocked by some of these queues.
- 竞争条件- 当应用程序工作取决于代码部分执行的顺序时引起。
- 优先级反转- 当较高优先级的任务由于某些资源被阻塞而等待较小优先级的任务完成时
- 死锁- 当一些队列无限等待已被其中一些队列阻塞的源(变量、数据等)时。
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. F.e. when we are making sure that some function/method is not double called. F.e. we have synchronization and trying to prevent it to be double called until it's completely finished. Here's some code for this concern:
How to find out what caused error crash report on IOS device?
什么时候使用同步?当我们需要等到任务完成时。Fe,当我们确保某些函数/方法不被重复调用时。Fe 我们有同步并试图防止它被双重调用,直到它完全完成。这是针对此问题的一些代码:
如何找出导致 IOS 设备上的错误崩溃报告的原因?
回答by Vipin
sync
or async
methods have no effect on the queue on which they are called.
sync
或async
方法对调用它们的队列没有影响。
sync
will block the thread fromwhich it is called and not the queue onwhich it is called. 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).
sync
将阻止该线程从调用它,而不是队列上调用它。它的属性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. If this method is called from the background thread, control will return to that thread instantaneously even when UI seems to be frozen. This is because async
call is made on DispatchQueue.main
因此,即使DispatchQueue.main.async
是异步调用,添加到其中的重型操作也可以冻结 UI,因为其操作是在主线程上串行执行的。如果从后台线程调用此方法,即使 UI 似乎被冻结,控制权也会立即返回该线程。这是因为async
调用是在DispatchQueue.main
回答by yoAlex5
GCD
allows you to execute a task synchronously
or asynchronously
[About][More]
GCD
允许您执行任务synchronously
或asynchronously
[关于] [更多]
synchronous
(block and wait) function returns a control when the task will be completed
synchronous
(block and wait) 函数在任务完成时返回一个控制
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
(dispatch andproceed) 函数立即返回一个控件,将任务分派到适当的队列开始,但不等待它完成。