Что произойдет, если у меня есть вложенные вызовы dispatch_async?
Это может быть глупый вопрос, но мне нужно спросить и прояснить это для себя.
Чтобы отправить блок в очередь для выполнения, используйте функции dispatch_sync
и dispatch_async
. Они оба берут очередь и блок в качестве параметров. dispatch_async
возвращается немедленно, асинхронно запуская блок, а dispatch_sync
блокирует выполнение до тех пор, пока не будет возвращен предоставленный блок. Вот несколько ситуаций:
Ситуация 1
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_async(queue, ^{
NSLog(@"this is statement1");
});
});
Ситуация 2
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_sync(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_sync(queue, ^{
NSLog(@"this is statement1");
});
});
Ситуация 3
{
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_sync(queue, ^{
NSLog(@"this is statement1");
});
});
Ситуация 4
{
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_sync(queue, ^{
[self goDoSomethingLongAndInvolved];
dispatch_async(queue, ^{
NSLog(@"this is statement1");
});
});
}
И goDoSomethingLongAndInvolved
есть
-(void)goDoSomethingLongAndInvolved {
NSLog(@"goDoSomethingLongAndInvolved");
}
Я попытался запустить их в Xcode, но я не вижу различий вообще.
Итак, мои вопросы:
- Какое основное различие между этими ситуациями?
- Что делать, если я заменил
queue
на dispatch_get_main_queue()
?
Ответы
Ответ 1
Оператор dispatch_sync
ожидает, пока блок, который он закрывает, будет выполнен полностью. dispatch_async
немедленно возвращается и переходит к следующей строке кода, поэтому все внутри происходит параллельно.
Если queue
была создана последовательная очередь, то:
Ситуация 1 - Корневой блок немедленно возвращается. Внутри он ждет [self go....], а затем переходит к dispatch_async, который также возвращается немедленно.
Ситуация 2 - Если queue
была последовательной очередью, тогда был бы мертвый замок, так как он будет ждать, пока он закончит выполнение. Поскольку вы имеете дело с асинхронным, этот блок будет выполняться параллельно. (Спасибо, @Ken Thomases)
Ситуация 3 - здесь нет необходимости dispatch_sync
. Это вызывает тупик.
Ситуация 4 - Ожидает [self...], а затем немедленно возвращается.
Если вы замените queue
основной очередью, тогда не забудьте dispatch_sync
в главной очереди, потому что это вызовет тупик (это не произойдет, если отправлено не из основного потока, спасибо @Ken Thomases).
Чтобы понять это лучше, замените свою функцию следующим образом:
-(void)goDoSomethingLongAndInvolved:(NSString *)message {
for(int i = 0; i < 50; ++i) {
NSLog(@"%@ -> %d", message, i);
}
}
Вы будете ясно видеть, что происходит каждый раз, независимо от того, ждет он или нет. Удачи.