Difference between DispatchQueue.main.async and Di

2019-01-21 00:48发布

This question already has an answer here:

I have been using DispatchQueue.main.async since a long time to perform some UI related operations.

 But Swift provides DispatchQueue.main.async and DispatchQueue.main.sync and both are performed in main queue.

 So can anyone tell me difference between them? 

 And when should i use them?

 Thank you in advance.

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

        }
        DispatchQueue.main.sync {
            self.imageView.image = imageView
            self.lbltitle.text = ""

        }

2条回答
一纸荒年 Trace。
2楼-- · 2019-01-21 00:57

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)

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

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.

查看更多
Juvenile、少年°
3楼-- · 2019-01-21 01:08

Why concurrency? As soon as you add to your app heavy tasks 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 a thread safety which is not always as easy to control. F.e. when the 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.

There`s a few abstractions we need to be aware with.

  • Queues.
  • Synchronous/Asynchronous task performance.
  • Priorities.
  • Common troubles.

Queues.

Must be serial or concurrent. As well as global or private at the same time.

On the serial queue tasks will be finished one by one while on the concurrent queue tasks will be performed simultaneously and will be finished with unexpected schedule. Same group of tasks will take the way more longer time on the serial queue comparing to the concurrent.

You can create your own private queues (both serial or concurrent) or use already available global (system) queues. Only main queue is the serial one among the global queues.

It is highly recommended not to perform heavy tasks which is not referred with the UI work on the main queue (f.e. loading data from the network), but 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 with a different unexpected schedule and speed so some UI elements can be drawn before it's needed or when it's too late. It can crash the UI. 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.


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

.default queue which does't transfer the qos information. If it wasn't possible to detect the qos the qos will be used between .userInitiated and .utility.

Tasks can be performed synchronously or asynchronously.

  • Synchronous function returns the control on the current queue only after task is finished. It blocks the queue and waits until the task is finished.

  • Asynchronous function returns control on 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 following:

  • Race condition - caused when the app work depends on the order of the code parts execution.
  • Priority inversion - when the higher priority task wait of the smaller priority task is finished due to some resources are blocked
  • Deadlock - when the few queues are infinitely 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?

查看更多
登录 后发表回答