Подтвердить что ты не робот

Что произойдет, если у меня есть вложенные вызовы 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()?
4b9b3361

Ответ 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); 
    }
}

Вы будете ясно видеть, что происходит каждый раз, независимо от того, ждет он или нет. Удачи.