Is DispatchQueue.global(qos: .userInteractive).async same as DispatchQueue.main.async

IosSwiftGrand Central-DispatchQosDispatch Queue

Ios Problem Overview


I was going through the tutorial : https://www.raywenderlich.com/148513/grand-central-dispatch-tutorial-swift-3-part-1

And came across the definition of QoS class User-interactive. Its mentioned there that this should run on main thread. So, my question is then what is the difference between the

DispatchQueue.global(qos: .userInteractive).async{} 

and

DispatchQueue.main.async{}

Thanks!!

Ios Solutions


Solution 1 - Ios

The "quality of service" definitions are described here:

https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html

It looks like the "main" thread will have a QoS class of "User-interactive". However, just because a thread is created with a QoS of "User-interactive", does not mean that it is the "main" thread.

You can observe this in the Xcode debugger. Put a breakpoint inside the async block and look at the Debug Navigator active thread panel. When DispatchQueue.global(qos: .userInteractive).async{} is called from the main thread, it displays with a different name than the main thread.

In general, the main thread is considered the special thread where all view-related access should be performed. If something will consume any significant time, e.g. calling a web service, compressing a file, etc., you will want to run code in a separate queue, and when the process completes, return to the main queue where you update the user interface.

Note also that when using Xcode 9 with iOS 11, a warning will be emitted when a user-interface object is accessed from a non-main thread.

Solution 2 - Ios

These are not the same. They mean different things and you should use the one you mean. The main queue is userInteractive, but not every userInteractive queue is the main queue. This is discussed well by Apple in Building Responsive and Efficient Apps with GCD.

It is valid to have multiple queues running at the userInteractive level. This is appropriate if you need to make use of multiple cores simultaneously to perform computations that are required in order to maintain a smooth user interaction (usually some kind of animation). This is very rare to need, and should be done with care, but if you need to compute something on the main thread while also computing something on another core in order to keep up with user actions, that's what it's there for.

But there can be only one main queue. It happens to be userInteractive, but that's not its point. Most of UIKit is not thread safe and it is only valid to access those classes on the main queue, not just any userInteractive queue.

Queue priorities are more complex they appear at first. They can propagate from queue to queue, such that "low priority" queues may temporarily have high priority status. Apple tweaks how this works a lot to make the whole system more responsive. This is why it's so important to always express what you mean rather than relying on assumptions about how things might work under the covers. Even if your tests show you that two queues are always the same, that wouldn't be enough to know that they will be the same on all devices or for future versions of the OS.

Solution 3 - Ios

Anyone who says the .userInitiated global queue is the main thread is just wrong. It's a very high priority background queue, but it is a background queue (and it is concurrent, unlike the main thread).

Apple's own sample code and comments make the matter quite clear:

// This handler gets called on the main thread; dispatch to a background queue for processing.
DispatchQueue.global(qos: .userInitiated).async {

This proves beyond a shadow of a doubt that Apple believes the .userInitiated global queue is a "background queue" and not the "main thread".

Solution 4 - Ios

You can use DispatchQueue.global(qos: .userInteractive).async{} when you want to do something very fast in the background while the user is interacting with your app. This is rarely used because, as it has to happen so quickly, you probably can do it directly in the main queue.

You can check this lecture where this issue is quite clearly explained.

Solution 5 - Ios

The main queue does indeed run on the main thread like you say.

The global queues are concurrent queues and from the main page for dispatch_get_global_queue:

Unlike the main queue or queues allocated with dispatch_queue_create(), the global concurrent queues schedule blocks as soon as threads become available ("non-FIFO" completion order). The global concurrent queues represent three priority bands:

   •   DISPATCH_QUEUE_PRIORITY_HIGH
   •   DISPATCH_QUEUE_PRIORITY_DEFAULT
   •   DISPATCH_QUEUE_PRIORITY_LOW

Blocks submitted to the high priority global queue will be invoked before those submitted to the default or low priority global queues. Blocks submitted to the low priority global queue will only be invoked if no blocks are pending on the default or high priority queues.

So, they are queues which run on background threads as and when they become available. They're "non-FIFO" so ordering is not guaranteed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNishu_PriyaView Question on Stackoverflow
Solution 1 - IosDanielView Answer on Stackoverflow
Solution 2 - IosRob NapierView Answer on Stackoverflow
Solution 3 - IosmattView Answer on Stackoverflow
Solution 4 - IosceliuxView Answer on Stackoverflow
Solution 5 - IosZahurafzal MirzaView Answer on Stackoverflow