【问题标题】:Why a sync block of code always call on main thread?为什么同步代码块总是在主线程上调用?
【发布时间】:2019-03-27 23:32:18
【问题描述】:

我用 DispatchQueue 做了简单的测试:

DispatchQueue.global(qos: .background).sync {
  if Thread.isMainThread {
    print("Main thread")
  }
}

打印出来了:

Main thread

为什么这段代码在主线程上执行?它应该在后台线程上执行(它被添加到后台队列中),对吧?

【问题讨论】:

  • 来自sync函数的文档:“作为一种优化,这个函数在可能的情况下调用当前线程上的块。”
  • 不要混淆队列和线程。使用队列,让他们为您担心线程!

标签: ios swift concurrency dispatch-queue


【解决方案1】:

因为它实际上并不需要。您正在使用同步阻塞主线程。 iOS 选择只在主线程上执行它,而不是费心切换到(后台队列的)后台线程,因为无论如何主线程都被阻塞了,这并不重要。

Apple 关于同步功能的文档(和快速帮助)包括以下内容:

作为一种优化,此函数在可能的情况下调用当前线程上的块。

【讨论】:

    【解决方案2】:

    问题是你问错了问题。不要混淆队列和线程。使用队列并让它们根据需要重新调整线程。这正是我们排队的原因!你不必担心你在哪个线程上。所有需要知道的是你在正确的队列中,你可以这样发现:

    let q = DispatchQueue.global(qos: .background)
    q.sync {
        dispatchPrecondition(condition: .onQueue(q))
        print("it's okay! we're on the right queue") // yep
    }
    

    【讨论】:

    • 您好,感谢您的信息。我只是想对队列和线程有更多的了解!我很确定我对它们并不感到困惑,但仍然想知道为什么这个块发生在主线程上。我认为“优化”是一个可以接受的答案。
    • @Matt Marginally 相关的问题,但是否有最佳实践方法来做到这一点? pastebin.com/R5KeWrjY
    • @Alexander 这可能 最好的做法 (stackoverflow.com/questions/10330679/…) 但更好的做法是问问自己是否真的需要致电 main.sync首先。
    • 是的,如果您想在后台队列上完成工作,请编写您的代码,以便您的主队列可以启动该后台队列上的工作,然后继续,然后您的主队列代码可以收到通知当工作在后台队列中完成时,以某种方式(例如通过在主队列上调用的完成闭包)在下一个收益周期中。
    • @matt 在我的特定情况下,它是在我的 VC 管理的视图表视图上调用 reloadData()。有多种情况需要重新加载数据。有些在主线程上(@IBActions 的一部分),而有些在主线程外(异步 rx 代码)。
    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多