Цель-C: запустить объект в фоновом потоке - взаимодействовать как обычно? - PullRequest
5 голосов
/ 10 марта 2010

Я бы хотел, чтобы объект вызывался из основного потока

MyObj* backgroundObject = [[MyObj alloc] initInBackground];
BOOL result = [backgroundObject computeResult];

Но все методы backgroundObject вычисляются в другом потоке.

А также позволяет backgroundObj отправлять сообщения своему делегату. Как я могу сделать такую ​​вещь? Возможно ли это?

Ответы [ 5 ]

7 голосов
/ 11 марта 2010

Как уже отмечали другие, NSObject не существует ни в одном потоке, поток вступает в действие только тогда, когда вы начинаете выполнять его методы.

Мое предложение состоит в том, чтобы не использовать ручные потоки при каждом вызове метода для объекта, а вместо этого использовать NSOperations и NSOperationQueue. Имейте NSOperationQueue как переменную экземпляра объекта, и имейте вызовы к различным методам на объекте, создайте NSOperations, которые вставлены в очередь. NSOperationQueue будет обрабатывать эти операции в фоновом потоке, избегая всего ручного управления потоками, которое вам потребуется для множественного доступа к методам.

Если вы установите для этого NSOperationQueue максимальный счетчик параллелизма, равный 1, вы также можете избежать блокировки общих ресурсов в объекте между различными операциями, которые будут выполняться в фоновом потоке (конечно, вам все равно придется блокировать переменные экземпляра к которому можно получить доступ из внешнего мира).

Для обратных вызовов для делегатов или других объектов я бы рекомендовал использовать -performSelectorOnMainThread:withObject:waitUntilDone, чтобы вам не приходилось думать о том, чтобы сделать эти методы делегатов поточно-безопасными.

Подробнее см. В Руководстве по программированию .

6 голосов
/ 10 марта 2010

Конечно, вы можете использовать NSThread для этого, а backgroundObject использовать performSelectorOnMainThread: для связи с делегатом.

2 голосов
/ 10 марта 2010

Объекты не существуют в потоках AFAIK. Функция, которую вы отправляете объекту, всегда будет выполняться в потоке, из которого вы его отправили (если только вы не используете NSThread или executeSelectorOnMainThread или что-то в этом духе).

1 голос
/ 08 июня 2012

Что вам нужно, это NSOperation и параметр блока / делегата для уведомления вызывающего абонента о завершении.

Посмотрите документацию NSOperation и NSOperationQueues

0 голосов
/ 10 июня 2012

Вы должны использовать GCD :

/*
 * I didn't initalised your object in background, because
 * because in the most cases you need your object to stick around
 * and only perfom the time consimung calculations in background
 */

MyObj* backgroundObject = [[MyObj alloc] initInBackground];
...

- (void)startBackgroundTask {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //in a perfectly async non blocking block :-)
        BOOL result = [backgroundObject computeResult];

        dispatch_async(dispatch_get_main_queue(), ^{
        //post your result, or do something else with your result
            [[NSNotificationCenter defaultCenter] postNotificationName:"backgroundComputeResultDone" object:[NSNumber numberWithBool:result]];

            if (result) {
                //do some stuff
            }
        });
    });
}

Может быть, вы можете посмотреть на эти два видео от Apple здесь :

  • WWDC 2011 - Сессия 210 - Освоение Гранд Сентрал Диспетчер
  • WWDC 2011 - Сессия 308 - Блоки и Великая центральная диспетчеризация на практике
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...