У вас есть пара проблем:
Во-первых, вы используете dispatch_async()
. Эта функция ставит в очередь блок кода для выполнения асинхронно в каком-то другом потоке.
Это имеет два важных следствия:
- Выполнение блока кода непредсказуемо ; он может выполняться до, одновременно или после остальной части кода, поставившего его в очередь.
- Если
queue
- это параллельная очередь (по умолчанию), тогда остальные 19 блоков также могут выполнять одновременно; фактически, все 20 блоков могут работать одновременно, без гарантии порядка.
Чтобы гарантировать, что вы напечатаете «xxx», «yyy», «xxx», «yyy», ... вы должны убедиться, что все начальные блоки выполняются последовательно , и что каждый подблок выполняется синхронно .
Итак, ваш код должен выглядеть следующим образом:
// `queue` must be created as a serial queue
dispatch_queue_t queue = dispatch_queue_create("xxxs",DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 20; i++) {
dispatch_async(queue, ^{
NSLog(@"xxx");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"yyy");
});
});
}
l oop немедленно создаст и поставит в очередь 20 блоков кода, добавляя их в серийный queue
по порядку. Поскольку queue
является последовательным, только один блок в очереди будет выполняться за раз, а второй блок в очереди не начнется, пока не завершится первый.
При выполнении первого блока он печатает «xxx» "затем синхронно ставит блок в очередь для выполнения в основном потоке. Синхронный вызов останавливает поток (первый блок) до тех пор, пока этот подблок не будет выполнен в основном потоке.
После завершения блока «yyy» вызов dispatch_sync
возвращается, и первый блок возобновляет выполнение и выходы. Второй блок на queue
начинает выполняться, и все это повторяется, пока не будут выполнены все блоки.
Сказав все это, поскольку вы хотите, чтобы весь этот код выполнялся последовательно, на самом деле нет никакого преимущества для создания последовательной очереди и добавления отдельных блоков. Этот код делает то же самое, но намного проще:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
for (int i = 0; i < 20; i++) {
NSLog(@"xxx");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"yyy");
});
}
});
Я надеюсь, что это поможет вам понять очереди и синхронные и асинхронные диспетчерские вызовы.