DispatchQueue.global(qos: .userInteractive).async 是否与 DispatchQueue.main.async 相同

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

我正在学习教程: https://www.raywenderlich.com/148513/grand-central-dispatch-tutorial-swift-3-part-1

并且遇到了 QoS 的定义 class 用户交互。 它在那里提到这应该在主线程上 运行 。 所以,我的问题是

之间有什么区别
DispatchQueue.global(qos: .userInteractive).async{} 

DispatchQueue.main.async{}

谢谢!!

此处描述了 "quality of service" 定义:

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

看起来 "main" 线程的 QoS class 为 "User-interactive"。但是,仅仅因为创建的线程的 QoS 为 "User-interactive",并不意味着它是 "main" 线程。

您可以在 Xcode 调试器中观察到这一点。在异步块内放置一个断点并查看 Debug Navigator 活动线程面板。当从主线程调用 DispatchQueue.global(qos: .userInteractive).async{} 时,它显示的名称与主线程不同。

一般来说,主线程被认为是特殊线程,所有与视图相关的访问都应在其中执行。如果某件事会消耗大量时间,例如调用 Web 服务、压缩文件等,您需要 运行 在单独的队列中编码,当该过程完成时,return 到您更新用户界面的主队列。

另请注意,当使用 Xcode 9 和 iOS 11 时,当从非主线程访问用户界面对象时将发出警告。

如果您想在用户与您的应用交互时在后台快速执行某些操作,则可以使用 DispatchQueue.global(qos: .userInteractive).async{}。这很少使用,因为它必须如此迅速地发生,您可能可以直接在主队列中进行。

您可以查看此 lecture,其中对这个问题的解释非常清楚。

这些不一样。它们意味着不同的东西,你应该使用你的意思。主队列是userInteractive,但不是每个userInteractive队列都是主队列。 Apple 在 Building Responsive and Efficient Apps with GCD.

中对此进行了很好的讨论

在 userInteractive 级别有多个队列 运行 是有效的。如果您需要同时使用多个内核来执行维持流畅的用户交互(通常是某种动画)所需的计算,这是合适的。这很少需要,并且应该小心完成,但是如果您需要在主线程上计算一些东西,同时还要在另一个核心上计算一些东西以便跟上用户操作,这就是它的用途。

但是主队列只能有一个。它恰好是 userInteractive,但这不是它的重点。大多数 UIKit 都不是线程安全的,它只对访问主队列上的 类 有效,而不仅仅是任何 userInteractive 队列。

队列优先级更复杂,它们一开始就出现了。它们可以从一个队列传播到另一个队列,这样 "low priority" 个队列可能暂时具有高优先级状态。 Apple 调整了它的工作方式,使整个系统更具响应性。这就是为什么始终表达您的意思而不是依赖于关于事情在幕后如何运作的假设如此重要的原因。即使您的测试显示两个队列始终相同,也不足以知道它们在所有设备上或对于 OS.

的未来版本都相同。

任何说 .userInitiated 全局队列是主线程的人都是错误的。它是一个非常高优先级的后台队列,但它是一个后台队列(而且它是并发的,不像主线程)。

Apple 自己的 sample code and comments 把事情说得很清楚了:

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

这毫无疑问地证明了 Apple 认为 .userInitiated 全局队列是 "background queue" 而不是 "main thread".

主队列确实像你说的那样在主线程上运行。

全局队列是并发队列,来自dispatch_get_global_queue的主页:

与使用 dispatch_queue_create() 分配的主队列或队列不同,全局并发队列在线程可用时立即调度块("non-FIFO" 完成顺序)。全局并发队列代表三个优先级带:

   •   DISPATCH_QUEUE_PRIORITY_HIGH
   •   DISPATCH_QUEUE_PRIORITY_DEFAULT
   •   DISPATCH_QUEUE_PRIORITY_LOW

提交到高优先级全局队列的块将在提交到默认或低优先级全局队列的块之前被调用。只有在默认或高优先级队列上没有待处理的块时,才会调用提交到低优先级全局队列的块。

因此,它们是在后台线程可用时 运行 的队列。他们是 "non-FIFO",因此不能保证一定会订购。