DispatchQueue.global.async中的代码是否按顺序执行?

时间:2019-07-24 16:35:42

标签: swift macos grand-central-dispatch

我有一些看起来像这样的代码:

DispatchQueue.global(qos: .userInitiated).async {
    self.fetchProjects()
    DispatchQueue.main.async {
          self.constructMenu()
    }
}

我的问题是全局块中的块是否按顺序执行?当我添加打印语句时,它们总是以相同的顺序执行,但是我不确定在查看文档时是否很幸运,它说:

  

提交到返回队列中的任务是相对于彼此并发安排的。

我想知道是否有人可以对此进行解释?

编辑:

抱歉,我认为我没有把问题弄清楚。我希望方法constructMenu仅在fetchProjects完成后才被调用。据我所知(通过记录打印语句)是这种情况。

但是我真的不确定为什么,如果上述Apple文档所说的(每个任务是同时安排的)是真的。

是异步块中的代码总是串行执行,还是使用DispatchQueue.main似乎是串行执行代码,还是只是运气好,在某个时候constructMenu实际返回之前 fetchProjects

3 个答案:

答案 0 :(得分:1)

是的,代码块作为块提交,并且这些块按顺序运行。因此,对于您的示例:

DispatchQueue.global(qos: .userInitiated).async {
    self.fetchProjects()
    DispatchQueue.main.async {
          self.constructMenu()
    }
}

fetchProjects()必须先完成constructMenu的入队。这里没有魔术。 {...}之间的块将作为一个块提交。在将来的某个时候它将执行。但是不会以任何精细的方式考虑块的各个部分。它们将从顶部fetchProjects开始,然后将执行下一行代码DispatchQueue.main.async,该代码接受另一个块作为参数。编译器对这些块一无所知。它只是将它们传递给函数,然后这些函数将它们放在队列中。

答案 1 :(得分:1)

  

我希望方法constructMenu仅在fetchProjects完成后才被调用。据我所知(通过记录打印语句)是这种情况。

是的,就是这种情况。

  

但是我真的不确定为什么上面苹果文件中所说的(每个任务是同时安排的)是真的。

Apple的文档说,两个相互独立的调度程序可以同时运行。

考虑:

DispatchQueue.global(qos: .userInitiated).async {
    foo()
}

DispatchQueue.global(qos: .userInitiated).async {
    bar()
}

在这种情况下,foobar可能会同时运行。这就是Apple所说的“同时计划提交给返回队列的任务”。

但是请考虑:

DispatchQueue.global(qos: .userInitiated).async {
    foo()
    bar()
}

在这种情况下,bar不会运行,直到我们从foo返回。

  

是异步块中的代码总是串行执行,还是使用DispatchQueue.main似乎是串行执行代码,还是只是运气好,在某个时候constructMenu真的在fetchProjects之前返回?

不涉及运气。除非您从DispatchQueue.main.async返回,否则它永远不会到达fetchProjects行。

不过,有一个相当重要的警告。假设fetchProjects在提取完成之前不会返回。这意味着fetchProjects最好不要自行启动任何异步进程(即没有网络请求)。如果是这样,您可能想为其提供一个完成处理程序,并将调用移至该完成处理程序中的constructMenu

答案 2 :(得分:0)

DispatchQueue.global是并发队列,这意味着所有提交的任务同时异步运行(如果需要的话,可以依次创建一个自定义队列

let serial = DispatchQueue(label: "com.queueName")
serial.sync {
    ///
}