Чем отличаются способы вызова моего метода в отдельном потоке?

У меня есть метод расчета данных (пусть это будет «myMethod:»), и я хочу переместить вызов в другой поток, потому что я не хочу блокировать свои основные функции пользовательского интерфейса. Итак, я начал исследовать, как вызвать мой метод в другом потоке. Насколько я понимаю, в настоящее время есть много разных способов сделать это. Вот список:

a) с использованием чистых потоков (доступно начиная с iOS 2.0):

[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray];

b) с использованием простого ярлыка (доступно с iOS 2.0). Доступен из унаследованного NSObject, но метод также принадлежит классу NSThread:

[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];

c) с использованием нового подхода к очередям Grand Central Dispatch (доступен с iOS 4.0):

dispatch_async(dispatch_get_global_queue(0, 0),
  ^ {
      [self myMethod:_myParamsArray];
    });

d) каким-то образом, используя некоторые классы, такие как NSOperation, NSBlockOperation или NSOperationQueue, хотя и не уверен, как именно это сделать (некоторые примеры будут оценены)

В настоящее время я использовал случай «b», но мне интересно узнать о плюсах и минусах и других связанных предложениях по этому поводу.

ОБНОВЛЕНИЕ: e) также нашел другой способ выполнения аналогичных потоковых операций - Выполнить циклы . Вот выдержка из документации Apple:

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

IMHO, более или менее вы имеете дело с одной и той же задачей - как вызвать свой метод в отдельном потоке для его асинхронной операции.

UPDATE2: Уже был некоторый опыт работы с NSInvocationOperation и NSOperationQueue и ИМХО, это довольно удобно.Согласно документам Apple, GCD и NSOperations являются предпочтительным способом реализации многопоточности. Кроме того, NSOperations работает на GCD, начиная с iOS 4.0. Короче говоря, вы создаете экземпляр NSIvocationOperation (как вызов вашего метода), затем создаете экземпляр NSOperationQueue и добавляете вызов в очередь. NSOperationQueue - это достаточно умная вещь, вы можете создавать экземпляры нескольких объектов NSIvocationOperation (обертывая вызовы ваших методов) и их в NSOperationQueue. В остальном уверены. NSOperationQueue определяет, сколько параллельных потоков необходимо для выполнения вызовов (NSInvocationOperation), и обрабатывает это за вас. Он может выполнить первый вызов в потоке A, затем второй в потоке B, третий в потоке C и далее в потоке B, поэтому вам не нужно об этом беспокоиться. Но если вы хотите, вы можете указать, какое максимальное количество потоков NSOperationQueue может использовать для выполнения вызовов (например, 1), но мне это не нужно. По умолчанию все задачи выполняются не в основном потоке, поэтому очереди операций по умолчанию асинхронны. Кроме того, если вы хотите выполнять вызовы своих методов (каждый из которых заключен в отдельный NSInvocationOperation) в строгой очереди, вы можете добавить зависимости, и поэтому NSOperationQueue сохранит порядок вызова методов. Вот пример:

// wrap your method call into NSInvocationOperation object
NSInvocationOperation *currentOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(yourMethodCall) object:nil];

// _sharedOperationQueue is a shared NSOperationQueue 
// get all executing operations from the queue and get the last operation
_lastOperation = [[_sharedOperationQueue operations] lastObject];

// check if _lastOperation is not nil
if (_lastOperation) {

    // if not then add dependency, so the calls would be performed in a queue
    [currentOperation addDependency:_lastOperation];
}

// say - execute my method (operation)
[_sharedOperationQueue addOperation:currentOperation];

_lastOperation = currentOperation; // mark as last operation for adding dependency to the next operation

// the queue will retain invocation operation so you will release
[currentOperation release];

 ..... you can create another NSInvocationOperation and add it to the queue....

Что касается RUNLOOP, тем не менее, иногда вы столкнетесь с ними, например, при запуске / планировании таймера или установлении соединений NSURL. IMHO, цикл выполнения можно сравнить с очередью задач, выполняемых в одном потоке. IMHO runloop - это указатель на поток, который работает как очередь: у него есть задачи, которые могут генерировать события, и они будут помещены в конец очереди в этом потоке.По умолчанию все задачи в вашем приложении выполняются в одном цикле выполнения - в одном потоке. Я говорю, что это указатель, потому что, когда ваше приложение генерирует события, оно должно знать, куда поместить это событие (событие касания или другой обратный вызов делегата) для выполнения. Конечно,вы должны прочитать о циклах выполнения для более подробной информации, потому что это только мои мысли.

31
задан Centurion 30 March 2012 в 08:01
поделиться