2015-05-28 2 views
0

У меня есть часть кода (с блоком завершения), который я бы хотел запустить несколько раз (из цикла FOR), но я хочу, чтобы операция выполнялась одна одним.Запуск блока завершения несколько раз «Один за одним»

Чтобы попытаться объяснить это немного лучше ... (Макс Параллельная работа = 1, Элементы For() Loop = 3)

  1. Begin Для() в пункте 0
  2. Начало работы для элемент 0
  3. Завершение операции по для пункта 0
  4. цикла For Loop() в пункте 1
  5. Start о peration по пункту 1
  6. Завершение из операции по пункту 1
  7. петля для() по пункту 2
  8. Начать операцию по пункту 2
  9. Завершение из операции по пункту 2
  10. End For() по позиции 2

Сделали это решение, но, похоже, t о запуске сразу и не один на один ..

// Batch download 
    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 

    for (Item *item in ItemArray) { 
     [queue addOperationWithBlock:^{ 
      if (![[ItemClient sharedClient] isCachedItem:item]) { 
       // Item not yet cached 

       [[ItemClient sharedClient] cacheItem:item completion:^(NSError *error) { 
         // Complete, next in FOR loop 
       }]; 
      } else { 
       // Item already cached 
       // Complete, next in FOR loop 
      } 
     }]; 
    } 
+0

Почему вы добавить его к NSOperationQueue? Если вы хотите, чтобы он выполнялся последовательно (синхронно), все, что вам нужно сделать, это выполнить блок как функцию: 'block();' – danielmhanover

+0

Вы знаете, что одно ореховое решение - это рекурсия. – uchuugaka

ответ

0

Я полагаю, что [ItemClient cacheItem:completion:] делает некоторую давно запущенную часть работы, прежде чем он вызывает обработчик завершения, и это то, что вы хотите ждать, прежде чем начать следующий запрос.

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

Проще всего сделать, чтобы переписать [ItemClient cacheItem:completion:] так, чтобы он был синхронным. Другими словами, он просто выполняет работу, блокируя текущий поток и не нуждается в параметре завершения. NSOperationQueue помещает эти операции в фоновый поток для вас в любом случае, поэтому вы можете просто использовать этот поток для выполнения своей работы.

В качестве альтернативы, вы можете использовать семафор, чтобы заблокировать до завершения обратного вызова не происходит:

dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
[[ItemClient sharedClient] cacheItem:item completion:^(NSError *error) { 
    dispatch_semaphore_signal(semaphore); 
}]; 
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 
Смежные вопросы