Разблокирование Вашего пользовательского интерфейса

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

Задержка выполнения операций

Если Вы переносите операции, которые могут быть задержаны или ворваны блоки и выполнены инкрементно, делание так может помочь производительности. Операции, которые являются итеративными или модульными в природе, такими как вычисления царапины, могут обычно выполняться в маленьких блоках. Путем выполнения нескольких из этих вычислений во время простоя с помощью асинхронных уведомлений можно избежать блокировать основной поток. Для регистрации для уведомлений времени простоя Вы просто отправили бы объект уведомления на очередь по умолчанию и попросили бы ее быть диспетчеризированными во время простоя, как показано в следующем примере:

NSNotification* myNotification = [NSNotification notificationWithName:@"MyIdleNotification" object:myIdleHandlerObject];
 
[[NSNotificationQueue defaultQueue] enqueueNotification:myNotification postingStyle:NSPostWhenIdle];

Таймеры предлагают другой способ сделать мелкие суммы работы над более равными интервалами. Преимущество таймеров состоит в том, что они стреляют в известное время. Недостаток - то, что они стреляют независимо от того, насколько занятый Ваше приложение, который мог все еще вызвать заметную задержку. Для получения информации о том, как установить таймер, посмотрите, что Таймер Программирует Темы.

Используя выполненных наблюдателей цикла

Другой способ задержать работу состоит в том, чтобы сцепиться в циклы выполнения потоков Вашего приложения. Путем добавления CFRunLoopObserver к циклу выполнения можно получить уведомления в определенные моменты в выполнении того цикла выполнения. Например, Вы можете быть уведомлены, прежде чем таймеры обрабатываются, прежде чем входные источники обрабатываются, или прежде или после снов цикла выполнения.

Для создания наблюдателя цикла выполнения необходимо сначала определить функцию обратного вызова типа CFRunLoopObserverCallBack. Следующий код показывает демонстрационную реализацию этого метода. info параметр содержит данные, которые Вы хотите, передал Вашему обработчику, когда это вызывают, который в этом случае является экземпляром вымышленного MyObject.

void MyRunLoopObserver(CFRunLoopObserverRef observer,
                            CFRunLoopActivity activity,
                            void* info)
{
    MyObject* theObject = (MyObject*)info;
 
    // Perform your tasks here.
}

После определения функции обратного вызова необходимо создать наблюдателя цикла выполнения и установить ее на текущем цикле выполнения. Следующий код показывает Вам, как сделать это от метода Какао. Код запрашивает, чтобы функция обратного вызова была выполнена, прежде чем любые таймеры обрабатываются или прежде чем заснет цикл выполнения. Обратите внимание на то, что последний параметр к CFRunLoopObserverCreate self переменная, которая, как предполагается, является экземпляром MyObject, который ожидает обработчик обратного вызова.

- (void) installRunLoopObserver
{
    CFRunLoopObserverRef myObserver = NULL;
    int myActivities = kCFRunLoopBeforeTimers | kCFRunLoopBeforeWaiting;
 
    // Create the observer reference.
    myObserver = CFRunLoopObserverCreate(NULL,
                            myActivities,
                            YES,        /* repeat */
                            0,
                            &MyRunLoopObserver,
                            (void*)self);
 
    if (myObserver)
    {
        // Now add it to the current run loop
        CFRunLoopAddObserver(CFRunLoopGetCurrent(),
                            myObserver,
                            kCFRunLoopCommonModes);
    }
}

Используя потоки

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

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