Как изменить приоритет пользовательской очереди GCD? - PullRequest
18 голосов
/ 01 апреля 2012

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

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

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

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

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

Ответы [ 3 ]

43 голосов
/ 01 апреля 2012

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

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

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

7 голосов
/ 01 апреля 2012

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

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

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

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

1 голос
/ 02 апреля 2012

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

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

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

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

...