【问题标题】:Dispatch queue blocks main thread调度队列阻塞主线程
【发布时间】:2018-06-26 00:19:36
【问题描述】:

我有多个任务要放入在后台线程中运行的串行/并发队列中。每个任务将 fetch 来自 api(async) 的数据,然后是 copyItem(sync,取决于 fetch 的资源)。下面的代码阻塞了主线程。但是,如果我只将 copyItem 分配给队列,则不会阻塞主线程。为什么我不能在后台线程中运行整个块?

let serialQueue = DispatchQueue(label: "queue", qos: .background)
tableView.selectedRowIndexes.forEach { row in

  serialQueue.async {   

    InitData.fetch("someUrl") { initData in
      let fileManager = FileManager()                
      do {
         try fileManager.copyItem(atPath: "pathA", toPath: "pathB")
      } catch let error {
         print(error)
      }
    }
  }
}

这不会阻塞主线程:

tableView.selectedRowIndexes.forEach { row in

  InitData.fetch("someUrl") { initData in
    let fileManager = FileManager()
    let workItem = DispatchWorkItem {          
      do {
        try fileManager.copyItem(atPath: "pathA", toPath: "pathB")
      } catch let error {
        print(error)
      }
    }
    DispatchQueue.global(qos: .background).async(execute: workItem)
  }
}

【问题讨论】:

  • 如果在您的第​​一个代码块中,您可以在调用 print(Thread.current.isMainThread) 之前调用:copyItem
  • 返回真

标签: ios swift


【解决方案1】:

我们可以从您的症状中推断出InitData.fetch 有两个参数:一个字符串 ("someUrl") 和一个回调,并将回调提交给 主队列 执行。当您致电InitData.fetch 时,您在哪个队列中并不重要。重要的是InitData 最终(异步)用于调度回调执行的队列。也许你可以告诉它你希望它使用哪个队列,但显然在你编写的程序中,它使用了主队列。

【讨论】:

  • 这是否意味着无法在后台运行fetch -> copyItem 如果InitData.fetch 必须是异步的?
  • @vincentf 在你的解决方案中使用DispatchWorkItem,如果你注意到,你已经在这样做了
猜你喜欢
  • 2017-09-13
  • 2023-03-06
  • 2019-02-12
  • 1970-01-01
  • 2014-10-16
  • 2018-02-16
  • 1970-01-01
  • 2015-12-29
相关资源
最近更新 更多