Поиск…


Вступление

Связанная тема: Grand Central Dispatch

Синтаксис

  • dispatch_async - запускает блок кода в отдельной очереди и не останавливает текущую очередь. Если очередь находится в другом потоке, чем тот, на который был вызван метод dispatch_async, код в блоке будет работать во время кода после того, как dispatch_async также будет запущен
  • dispatch_sync - Выполняет блок кода в отдельной очереди, и не остановить текущую очередь. Если очередь находится в другом потоке, чем тот, на который был вызван метод dispatch_async, будет выполняться код в блоке, а выполнение в потоке, где был вызван метод, будет возобновляться только после завершения

параметры

очередь Очередь, в которой будет выполняться код в блоке отправки. Очередь похожа (но не совсем такая же, как) на поток; код в разных очередях может выполняться параллельно. Используйте dispatch_get_main_queue чтобы получить очередь для основного потока. Чтобы создать новую очередь, которая, в свою очередь, создает новый поток, используйте dispatch_queue_create("QUEUE_NAME", DISPATCH_QUEUE_CONCURRENT) . Первый параметр - это имя очереди, которое отображается в отладчике, если вы приостановили пока блок все еще работает. Второй параметр не имеет значения, если вы не хотите использовать одну и ту же очередь для нескольких вызовов dispatch_async или dispatch_sync . В нем описывается, что происходит, когда другой блок помещается в одну очередь; DISPATCH_QUEUE_CONCURRENT вызовет запуск обоих блоков одновременно, в то время как DISPATCH_QUEUE_SERIAL заставит второй блок ждать завершения первого блока
блок Код в этом блоке будет запущен в очереди queue ; введите код, который вы хотите запустить в отдельной очереди. Полезный совет: если вы пишете это в Xcode, а аргумент блока имеет синий контур вокруг него, дважды щелкните по аргументу, и Xcode автоматически сделает пустой блок (это относится ко всем блочным аргументам в любой функции или методе)

замечания

Всякий раз, когда вы делаете что-то в отдельном потоке, который возникает при использовании очередей, важно поддерживать безопасность потоков. Некоторые методы, в частности, для UIView s, могут не работать и / или сбой в потоках, отличных от основного потока. Кроме того, убедитесь, что вы ничего не меняете (переменные, свойства и т. Д.), Которые также используются в основном потоке, если вы не учитываете это изменение

Запуск кода одновременно - Запуск кода при запуске другого кода

Скажите, что вы хотите выполнить в действии (в этом случае записывать «Foo»), делая что-то еще (записывая «Bar»). Обычно, если вы не используете параллелизм, одно из этих действий будет полностью выполнено, а другой запуск будет выполняться только после того, как он будет полностью завершен. Но с параллелизмом вы можете одновременно запускать оба действия:

dispatch_async(dispatch_queue_create("Foo", DISPATCH_QUEUE_CONCURRENT), ^{
    for (int i = 0; i < 100; i++) {
        NSLog(@"Foo");
        usleep(100000);
    }
});

for (int i = 0; i < 100; i++) {
    NSLog(@"Bar");
    usleep(50000);
}

Это будет записывать «Foo» 100 раз, приостанавливаясь на 100 мсек каждый раз, когда он регистрируется, но он будет делать все это в отдельном потоке. В то время как Foo регистрируется, «Bar» также будет регистрироваться через 50 мс в одно и то же время. В идеале вы должны увидеть результат с сочетаниями «Foo» и «Bars»

Выполнение основной темы

При асинхронном выполнении задач обычно возникает необходимость обеспечить выполнение части кода в основном потоке. Например, вам может понадобиться асинхронно удалять REST API, но поместить результат в UILabel на экране. Перед обновлением UILabel вы должны убедиться, что ваш код запущен в основном потоке:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //Perform expensive tasks
    //...

    //Now before updating the UI, ensure we are back on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        label.text = //....
    });
}

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

Диспетчерская группа - ждет завершения других потоков.

dispatch_group_t preapreWaitingGroup = dispatch_group_create();

dispatch_group_enter(preapreWaitingGroup);
[self doAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    // Notify that this task has been completed.
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_enter(preapreWaitingGroup);
[self doOtherAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_notify(preapreWaitingGroup, dispatch_get_main_queue(), ^{
    // This block will be executed once all above threads completed and call dispatch_group_leave
    NSLog(@"Prepare completed. I'm readyyyy");
});

Обновление 1. Версия Swift 3.

let prepareGroup = DispatchGroup()
prepareGroup.enter()
doAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.enter()
doOtherAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.notify(queue: DispatchQueue.main) {
    // This block will be executed once all above threads completed and call dispatch_group_leave
    print("Prepare completed. I'm readyyyy")
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow