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

Как изменить приоритет пользовательской очереди GCD?

Я создал очередь GCD следующим образом:

dispatch_queue_t q = dispatch_queue_create("com.testcompany.myqueue", NULL);

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

dispatch_async(q, ^(void) {
    [self performHeavyCalculationAndUpdateUI];
});

Мое подозрение в том, что очередь по умолчанию имеет очень низкий приоритет. Как изменить приоритет этой очереди? Или есть что-то еще, что я должен сделать?

4b9b3361

Ответ 1

Если вы делаете вещи UIKit, в своем блоке, запущенном во вторичной очереди, отправляйте обновления пользовательского интерфейса обратно в основную очередь из вторичной очереди через:

dispatch_async(q, ^(void) {
    [self performHeavyCalculationAndUpdateUI];

    dispatch_async(dispatch_get_main_queue(), ^{
        // do my ui update
    });
});

Просто отправьте несколько строк, которые фактически обновляют интерфейс пользователя до основной очереди, и вы увидите, что это не вопрос приоритетов очереди, а просто убедитесь, что обновления пользовательского интерфейса происходят в основной очереди.

Ответ 2

Очереди отправки не имеют приоритета, который вы можете изменить.

Вы можете изменить целевую очередь ваших последовательных очередей с помощью функций dispatch_set_target_queue и использовать глобальную очередь DISPATCH_QUEUE_PRIORITY_HIGH. Это просто гарантирует, что он будет запланирован до любых других блоков, находящихся в очереди в очереди с невыполнением или низким приоритетом. Как только ваш блок начнет выполнение, он не будет работать быстрее или медленнее независимо от того, в какой очередь он был запланирован.

Ваша проблема, скорее всего, заключается в обновлении вашего графического интерфейса, см. ответ Роберта Рэнса.

Ответ 3

Я думаю, что вам не хватает точки асинхронных действий. И комментарий @RobertRyan о том, что обновления пользовательского интерфейса не отображаются быстро, если выполняется на вторичных очередях, неправильно. Все обновления пользовательского интерфейса должны выполняться в основной очереди. Период.

Но вернемся к GCD и асинхронной очереди. @Sven прав, что вы не можете изменить приоритет очередей отправки. Очереди в GCD работают в режиме FIFO (First In First Out), поэтому порядок, в котором вы их ставите, - это порядок, в котором они выполняются. Это часть того, почему использование GCD является потокобезопасным; вы гарантированно не столкнетесь с какими-либо проблемами из-за этого приоритета очереди FIFO. Второе, что нужно понять, это то, что при отправке очереди dispas_async ОС не гарантирует, когда эта очередь будет обработана. Это набор-и-забыть его тип процесса. Если вам нужно знать, когда очередь обрабатывается, вам нужно настроить обработчик блока завершения (вы заметите, что многие из Apple Framework начали внедрять это), чтобы получить уведомление об этом. Вот почему Apple предлагает вложить вызов dispatch_async в свой первый вызов dispatch_async и запросить основной поток для обновлений пользовательского интерфейса. Таким образом, ваш код будет выглядеть примерно так:

dispatch_async(q, ^{
    [self performHeavyCalculations];
    dispatch_async(dispatch_get_main_queue, ^{
        // some UI updates
    });
});

Из-за того, что GCD завершает и удаляет, отправка обновлений пользовательского интерфейса несинхронно обратно в основную очередь позволит обновлять пользовательские интерфейсы без заметной задержки для пользователя. Если ваши обновления пользовательского интерфейса зависят от результата выполненияHeavyCalculations, вам необходимо настроить обработчик завершения или схему делегирования, чтобы уведомить основную очередь о том, когда это будет завершено, чтобы обновления могли возникать. Если отставание между вычислениями и обновлением слишком велико, вам может потребоваться изучить то, что вы делаете в методе расчета, который занимает так много времени.