jjzjj

swift - 是否可以为 `DispatchQueue` 指定 `DispatchQueue.concurrentPerform` ?

coder 2023-09-12 原文

dispatch_apply将调度队列作为参数,它允许您选择要在哪个队列上执行 block 。

我的理解是,Swift中的DispatchQueue.concurrentPerform是用来代替dispatch_apply的。但是这个函数没有将调度队列作为参数。谷歌搜索后,我发现 this GCD tutorial其中有这段代码:

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

并解释:

This implementation includes a curious line of code: let _ = DispatchQueue.global(qos: .userInitiated). Calling this tells causes GCD to use a queue with a .userInitiated quality of service for the concurrent calls.

我的问题是,这真的可以指定 QoS 吗?如果是,怎么办?

我觉得没有办法为此指定队列,因为串行队列在这种情况下没有意义,只有最高 QoS 才真正有意义,因为这是一个同步阻塞函数。但我找不到任何文档说明为什么可以使用 dispatch_apply 指定队列,但不能使用 DispatchQueue.concurrentPerform 指定队列。

最佳答案

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

  1. concurrentPerform 调用 _swift_dispatch_apply_current .

  2. _swift_dispatch_apply_current使用 0 调用 dispatch_apply,即 DISPATCH_APPLY_AUTO,即 defined as一个...

    ... Constant to pass to dispatch_apply() or dispatch_apply_f() to request that the system automatically use worker threads that match the configuration of the current thread as closely as possible.

    When submitting a block for parallel invocation, passing this constant as the queue argument will automatically use the global concurrent queue that matches the Quality of Service of the caller most closely.

  3. 这也可以通过以下 dispatch_apply 调用 dispatch_apply_f 来确认,其中使用 DISPATCH_APPLY_AUTO 导致调用 _dispatch_apply_root_queue .如果你一直在 swift-corelibs-libdispatch 的兔子洞里翻滚,你会看到这实际上确实使用了一个全局队列,它与你当前的线程具有相同的 QoS。

最重要的是,指定 QoS 的正确方法是将对 concurrentPerform 的调用分派(dispatch)到所需的队列,例如:

DispatchQueue.global(qos: .userInitiated).async {
    DispatchQueue.concurrentPerform(iterations: 3) { (i) in
        ...
    }
}

这很容易通过添加断点并在 Xcode 调试器中查看队列来凭经验验证:


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

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

    DispatchQueue.concurrentPerform(iterations: 3) { (i) in
        ...
    }
}

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

同样,这很容易通过经验验证:


参见 WWDC 2017 视频 Modernizing Grand Central Dispatch有关 DISPATCH_APPLY_AUTOconcurrentPerform 的讨论。

关于swift - 是否可以为 `DispatchQueue` 指定 `DispatchQueue.concurrentPerform` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54775099/

有关swift - 是否可以为 `DispatchQueue` 指定 `DispatchQueue.concurrentPerform` ?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  6. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  7. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  8. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  9. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  10. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

随机推荐