Сериализация работы в очереди последовательной отправки находится в единице работы, которая непосредственно отправляется в очередь. После того, как выполнение достигнет конца представленного закрытия (или оно вернется), можно выполнить следующий блок работы в очереди.
Важно отметить, что любые другие асинхронные задачи, которые могут быть запущены при закрытии, все еще могут работать (или, возможно, даже не запущены), но они не рассматриваются.
Например, для следующего кода:
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")
}
Выходной сигнал будет что-то вроде:
Start
Совершено первое
Начало
Совершено второй
через 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")
}
Выходной сигнал будет что-то вроде:
Start
10 секунд
Совершено первое
Start
через 10 секунд
Done второго
Обратите внимание, что на этот раз, потому что 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()
, которые принимают параметр тайм-аута.
это FAN-TASTIC! вопрос: если DispatchGroup является нерешенным идентификатором, значит ли это, что я на Swift 2? 1? (Я знаю, что я не на 3) Должен ли я использовать dispatch_group_create, dispatch_group_enter и dispatch_group_leave как в (например) http://commandshift.co.uk/blog/2014/03/19/using-dispatch-groups-to -wait-for-multiple-web-services /? – Michael
Правильно; Я по умолчанию Swift 3 :) Я должен, вероятно, очистить свой ответ, так как на данный момент это смесь из 2 и 3. – Paulw11
, вы думаете, что dispatch_group_wait необходимо? например, если бы у меня было 2 блока, как у вас в самом конце вашего ответа, не могли ли вызовы dispatch_group_enter и dispatch_group_leave реализовать сериализацию? (а выход будет таким же, как и у вашего второго блока?) – Michael