是否可以将DispatchQueue.concurrentPerform指定为DispatchQueue?

jjo*_*son 2 grand-central-dispatch swift

dispatch_apply 将调度队列作为参数,这使您可以选择在哪个队列上执行块。

我的理解是,DispatchQueue.concurrentPerform在Swift中是要替换的dispatch_apply。但是此函数不将调度队列作为参数。搜寻之后,我发现了这个GCD教程,其中包含以下代码:

let _ = DispatchQueue.global(qos: .userInitiated)
DispatchQueue.concurrentPerform(iterations: addresses.count) { index in
    // do work here
}
Run Code Online (Sandbox Code Playgroud)

并说明:

此实现包括一个奇怪的代码行:let _ = DispatchQueue.global(qos: .userInitiated)。调用此命令会导致GCD对.userInitiated并发调用使用具有服务质量的队列。

我的问题是,这实际上可以用来指定QoS吗?如果是这样,怎么办?

对于我来说,没有办法为此指定队列是有道理的,因为在这种情况下,串行队列没有意义,并且鉴于这是同步阻塞功能,因此只有最高的QoS才有意义。但是我找不到任何文档来说明为什么可以用来指定队列,dispatch_apply而用来不可能(?)DispatchQueue.concurrentPerform

Rob*_*Rob 5

作者尝试指定队列服务质量(QoS)的尝试不正确。在concurrentPerform如果可以使用当前队列的服务质量。您可以通过跟踪源代码来确认这一点:

  1. concurrentPerform来电_swift_dispatch_apply_current

  2. _swift_dispatch_apply_current来电dispatch_apply0,即 DISPATCH_APPLY_AUTO,它被定义为一个...

    ...传递给dispatch_apply()dispatch_apply_f()请求系统自动使用与当前线程的配置尽可能紧密匹配的工作线程的常数。

    提交用于并行调用的块时,将此常量作为queue参数传递将自动使用与调用者的服务质量最紧密匹配的全局并发队列。

  3. 也可以通过在的dispatch_apply调用dispatch_apply_f中进行确认,其中DISPATCH_APPLY_AUTO在的调用中使用结果_dispatch_apply_root_queue。如果继续翻滚swift-corelibs-libdispatch的麻烦,您会发现它实际上确实使用了与当前线程相同的QoS的全局队列。

最重要的是,指定QoS的正确方法是将呼叫分派concurrentPerform到所需的队列,例如:

DispatchQueue.global(qos: .userInitiated).async {
    DispatchQueue.concurrentPerform(iterations: 3) { (i) in
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

通过添加断点并查看Xcode调试器中的队列,可以很容易地凭经验验证这一点:

在此处输入图片说明


不用说,添加的建议let _ = ...是不正确的。考虑以下:

DispatchQueue.global(qos: .utility).async {
    let _ = DispatchQueue.global(qos: .userInitiated)

    DispatchQueue.concurrentPerform(iterations: 3) { (i) in
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这将以“实用” QoS运行,而不是“用户启动”。

同样,这很容易凭经验进行验证:

在此处输入图片说明


有关和的讨论,请参阅WWDC 2017视频“ 现代化中央中央调度程序” 。DISPATCH_APPLY_AUTOconcurrentPerform

  • 感谢您的详细回答。我知道教程中的代码可能是错误的,但 raywenderlich.com 教程通常非常可靠。 (2认同)