Нахавандипур Вандад
Шрифт:
Если активизировать метод класса currentThread, относящийся к классу NSThread, то выяснится, что блоковые объекты или функции C, направляемые вами в главную очередь, действительно работают в главном потоке:
Вывод данного кода будет примерно таким:
Итак, мы изучили, как с помощью GCD решаются задачи, связанные с пользовательским интерфейсом. Перейдем к другим темам — в частности, поговорим о том, как выполнять задачи параллельно, используя параллельные очереди (см. разделы 7.5 и 7.6), и как при необходимости смешивать создаваемый код с кодом пользовательского интерфейса.
7.5. Синхронное решение с помощью GCD задач, не связанных с пользовательским интерфейсом
Постановка задачи
Необходимо выполнять синхронные задачи, в которых не участвует код, связанный с пользовательским интерфейсом.
Решение
Воспользуйтесь функцией dispatch_sync.
Обсуждение
Иногда необходимо решать задачи, никак не связанные с пользовательским интерфейсом, либо осуществлять процессы, которые взаимодействуют и с пользовательским интерфейсом, но в то же время заняты решением долговременных задач. Например, вам может понадобиться загрузить изображение, а после загрузки отобразить его для пользователя. Процесс загрузки совершенно не связан с пользовательским интерфейсом.
Любая задача, не связанная с пользовательским интерфейсом, позволяет применять глобальные параллельные очереди, которые предоставляет GCD. Они могут выполняться как синхронно, так и асинхронно. Но синхронное выполнение не означает, что программа дожидается, пока выполнится определенный фрагмент кода, а потом продолжает работу. Это лишь означает, что параллельная очередь дождется выполнения вашей задачи и только потом перейдет к выполнению следующего блока кода, стоящего в очереди. Когда вы ставите в параллельную очередь блоковый объект, ваша собственная программа всегда продолжает работу, не дожидаясь, пока выполнится код, стоящий в очереди. Дело в том, что параллельные очереди (как понятно из их названия) выполняют свой код в неглавных потоках. (Из этого правила есть исключение: когда задача передается в параллельную или последовательную очередь посредством функции dispatch_sync, система iOS при наличии такой возможности запускает задачу в текущем потоке. А это может быть и главный поток в зависимости от актуальной ветви кода. Это специальная оптимизация, запрограммированная в GCD, и вскоре мы обсудим ее подробнее.)
Если вы отправляете синхронную задачу в параллельную очередь и в то же время отправляете синхронную задачу в другую параллельную очередь, то две эти синхронные задачи будут выполняться асинхронно друг относительно друга, так как относятся к двум разным параллельным очередям. Этот нюанс важно понимать, поскольку иногда необходимо гарантировать, что задача B начнет выполняться только после того, как завершится задача А. Чтобы обеспечить такую последовательность, эти две задачи нужно синхронно отправлять в одну и ту же очередь.
Синхронные задачи в диспетчерской очереди можно выполнять с помощью функции dispatch_sync. Все, что от вас требуется, — снабдить эту функцию описателем той очереди, в которой должна выполняться задача, а также блоком кода, который должен выполниться в данной очереди.
Рассмотрим пример. Данная функция выводит на консоль числа от 1 до 1000, всю последовательность подряд, и при этом не блокирует основной поток. Мы можем создать блоковый объект, выполняющий подсчет за нас, и синхронно (дважды) вызвать этот же блоковый объект:
Итак, попробуем активизировать этот блоковый объект с помощью GCD: