使用GCD时,我们希望等到两个异步块执行完成后再继续执行下一步 . 最好的方法是什么?
我们尝试了以下方法,但它似乎不起作用:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block1
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block2
});
// wait until both the block1 and block2 are done before start block3
// how to do that?
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block3
});
8 回答
通过Swift 3,Grand Central Dispatch提供了许多方法来解决您的问题 . 根据您的需要,您可以选择以下Playground片段中显示的其中一个 six patterns .
#1 . 使用DispatchGroup,DispatchGroup notify(qos:flags:queue:execute :)和DispatchQueue async(group:qos:flags:execute :)方法
Apple Developer并发编程指南states about DispatchGroup:
#2 . 使用DispatchGroup,DispatchGroup wait(),DispatchGroup enter()和DispatchGroup leave()方法
请注意,您也可以将
DispatchGroup
wait()
与DispatchQueue
async(group:qos:flags:execute:)
混合或混合DispatchGroup
enter()
和DispatchGroup
leave()
与DispatchGroup
notify(qos:flags:queue:execute:)
.#3 . 使用DispatchWorkItemFlags barrier属性和DispatchQueue DispatchQueue async(group:qos:flags:execute :)方法
来自Raywenderlich.com的Grand Central Dispatch Tutorial for Swift 3: Part 1/2文章给出了障碍的定义:
用法:
#4 . 使用DispatchWorkItem,DispatchWorkItemFlags barrier属性和DispatchQueue async(execute :)方法
#5 . 使用DispatchSemaphore,DispatchSemaphore wait()和DispatchSemaphore signal()方法
Soroush Khanlou在The GCD Handbook博文中写了以下几行:
Apple Developer API Reference还为
DispatchSemaphore
init(value:)初始化程序提供了以下讨论:用法:
#6 . 使用OperationQueue和BlockOperation
Apple Developer API参考说明了
OperationQueue
:用法:
使用调度组:请参阅here以获取示例,"Dispatch Queues"在Apple的"Dispatch Queues"章节中's iOS Developer Library' s并发编程指南
您的示例可能如下所示:
并可以产生这样的输出:
扩展JörnEyrich的答案(如果你赞成这个答案,请回答他的答案),如果你无法控制你的块的
dispatch_async
调用,可能是异步完成块的情况,你可以使用dispatch_group_enter
和dispatch_group_leave
来使用GCD组直 .在这个例子中,我们假装
computeInBackground
是我们无法改变的东西(想象它是委托回调,NSURLConnection completionHandler或其他),因此我们无权访问调度调用 .在此示例中,computeInBackground:completion:实现为:
输出(来自运行的时间戳):
另一个GCD替代方案是障碍:
只需创建一个并发队列,调度两个块,然后使用barrier调度最后一个块,这将使其等待其他两个块完成 .
我知道你问过GCD,但如果你想,
NSOperationQueue
也非常优雅地处理这类东西,例如:第一个答案基本上是正确的,但如果你想用最简单的方法来完成所需的结果,这里有一个独立的代码示例,演示了如何使用信号量(这也是调度组在幕后工作的方式,JFYI) :
上面的答案都很酷,但他们都错过了一件事 . group在您使用
dispatch_group_enter
/dispatch_group_leave
时输入的线程中执行任务(块) .这在创建的并发队列
demoQueue
中运行 . 如果我不创建任何队列,它将在 main thread 中运行 .并且还有第三种方法可以在另一个线程中执行任务:
当然,如上所述,你可以使用
dispatch_group_async
来获得你想要的东西 .不是说其他答案在某些情况下并不是很好,但这是我一直在谷歌用户的一个片段: