串行调度队列上的工作序列化是直接提交到队列的工作单元。一旦执行到达提交的闭包的末尾(或它返回),就可以执行队列中的下一个工作单元。
重要的是,任何其他可能由闭包启动的异步任务可能仍在运行(或者甚至可能尚未开始运行),但它们不被考虑。
例如,对于以下代码:
dispatch_async(serialQueue) {
print("Start")
dispatch_async(backgroundQueue) {
functionThatTakes10Seconds()
print("10 seconds later")
}
print("Done 1st")
}
dispatch_async(serialQueue) {
print("Start")
dispatch_async(backgroundQueue) {
functionThatTakes10Seconds()
print("10 seconds later")
}
print("Done 2nd")
}
输出会是这样的:
开始
第一次完成
开始
第二次完成
10 秒后
10 秒后
请注意,在分派第二个串行任务之前,前 10 秒的任务尚未完成。现在,比较一下:
dispatch_async(serialQueue) {
print("Start")
dispatch_sync(backgroundQueue) {
functionThatTakes10Seconds()
print("10 seconds later")
}
print("Done 1st")
}
dispatch_async(serialQueue) {
print("Start")
dispatch_sync(backgroundQueue) {
functionThatTakes10Seconds()
print("10 seconds later")
}
print("Done 2nd")
}
输出会是这样的:
开始
10 秒后
第一次完成
开始
10 秒后
第二次完成
请注意,这一次因为 10 秒任务是同步调度的,同步串行队列被阻塞,第二个任务直到第一个任务完成后才开始。
在您的情况下,您包装的操作很有可能会自己分派异步任务(因为这是网络操作的本质),因此仅靠串行分派队列是不够的。
您可以使用DispatchGroup 来阻止您的串行调度队列。
dispatch_async(serialQueue) {
let dg = dispatch_group_create()
dispatch_group_enter(dg)
print("Start")
dispatch_async(backgroundQueue) {
functionThatTakes10Seconds()
print("10 seconds later")
dispatch_group_leave(dg)
}
dispatch_group_wait(dg)
print("Done")
}
这将输出
开始
10 秒后
完成
dg.wait() 阻塞串行队列,直到 dg.leave 调用的数量与 dg.enter 调用的数量相匹配。如果您使用此技术,则需要小心确保包装操作的所有可能完成路径调用dg.leave。 dg.wait() 也有一些变体,它们采用超时参数。