2013-03-13 2 views
4

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

Какая хорошая методика для выполнения этих задач по одному, начиная с следующей задачи после того, как текущий завершает свой блок завершения?

Есть ли метод, отличный от подкласса NSOperation с серийным NSOperationQueue?

+0

Являются ли они все NSOperations? – TheJer

+0

Вы не хотите подклассифицировать «NSOperation»? Или у вас есть какое-то возражение против серийного 'NSOperationQueue'? – Rob

+0

Они добавляются в виде блоков с помощью addOperationWithBlock. Асинхронные методы не ждут, поэтому параллелизм 1 в очереди ничего не делает. – jarryd

ответ

6

Стандартные растворы:

  1. NSOperationQueue с maxConcurrentOperationCount из 1. Вы говорите, что не хотите этого делать, но вы не говорите, почему. Серийные очереди являются наиболее логичным решением.

    Например:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 
    
    [queue addOperationWithBlock:^{ 
        NSLog(@"Starting #1"); 
        sleep(3); 
        NSLog(@"Finishing #1"); 
    }]; 
    
    [queue addOperationWithBlock:^{ 
        NSLog(@"Starting #2"); 
        sleep(3); 
        NSLog(@"Finishing #2"); 
    }]; 
    
    [queue addOperationWithBlock:^{ 
        NSLog(@"Starting #3"); 
        sleep(3); 
        NSLog(@"Finishing #3"); 
    }]; 
    
  2. Если вы не хотите серийный NSOperationQueue, вы можете использовать стандартные параллельные очереди, но только делаете каждую операцию зависит от уровня одного. Вы будете добиваться последовательного поведения, которое вы ищете, без использования последовательной очереди.

    Например:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    
    NSOperation *operation; 
    NSOperation *previousOperation; 
    
    operation = [NSBlockOperation blockOperationWithBlock:^{ 
        NSLog(@"Starting #1"); 
        sleep(3); 
        NSLog(@"Finishing #1"); 
    }]; 
    [queue addOperation:operation]; 
    
    previousOperation = operation; 
    operation = [NSBlockOperation blockOperationWithBlock:^{ 
        NSLog(@"Starting #2"); 
        sleep(3); 
        NSLog(@"Finishing #2"); 
    }]; 
    [operation addDependency:previousOperation]; 
    [queue addOperation:operation]; 
    
    previousOperation = operation; 
    operation = [NSBlockOperation blockOperationWithBlock:^{ 
        NSLog(@"Starting #3"); 
        sleep(3); 
        NSLog(@"Finishing #3"); 
    }]; 
    [operation addDependency:previousOperation]; 
    [queue addOperation:operation]; 
    
  3. Вы также можете создать последовательную очередь НОД с dispatch_queue_create. Он достигает того же, что и первый вариант, за исключением использования GCD вместо NSOperationQueue.

    Например:

    dispatch_queue_t queue = dispatch_queue_create("com.ConnerDouglass.operationtest", 0); 
    
    dispatch_async(queue, ^{ 
        NSLog(@"Starting #1"); 
        sleep(3); 
        NSLog(@"Finishing #1"); 
    }); 
    
    dispatch_async(queue, ^{ 
        NSLog(@"Starting #2"); 
        sleep(3); 
        NSLog(@"Finishing #2"); 
    }); 
    
    dispatch_async(queue, ^{ 
        NSLog(@"Starting #3"); 
        sleep(3); 
        NSLog(@"Finishing #3"); 
    }); 
    
+1

Спасибо. Дело в том, что я добавляю вызов метода с помощью addOperationWithBlock, но поскольку они являются асинхронными методами, я получаю сообщение об ошибке «Операция не может быть выполнена. Слишком много открытых файлов», даже если для параметра параллелизма установлено значение 1, блоки отмечаются как завершена, так как асинхронные вызовы не ждут. – jarryd

+0

@ Helium3 Можете ли вы обновить свой вопрос с характером кода, который вы отправляете на задний план? Когда операции очередей, которые сами по себе, асинхронны, существуют разные подходы, но было бы полезно, если бы вы были более конкретными. В моем классе загрузчика файлов я подклассифицирую NSOperation и не устанавливаю 'isFinished' до тех пор, пока загрузка не будет выполнена, но я не хочу продолжать догадываться о том, что вы пытаетесь сделать. – Rob

+0

@ Helium3 В дополнение к подклассу «NSOperation» и ручному управлению, когда вы устанавливаете 'isFinished', вы также можете создать две операции для каждого файла, один из которых - запуск операции async, другой - обработчик завершения операции async. И вы можете сделать следующую операцию зависимой от операции завершения предыдущего. См. Http://stackoverflow.com/questions/14195706/multiple-locations-in-google-map-mkmapitem/14198584#14198584 для примера. – Rob

0

А что-то вроде этого:

-(void)start 
{ 
    // Start the async chain 
    [self performSelectorInBackground:@selector(action1) withObject:nil]; 
} 
-(void)notifyDone:(NSNumber *)taskID 
{ 
    NSLog(@"Done with task #%i", taskID.intValue); 
} 
-(void)action1 
{ 
    // Do some fancy async stuff here 
    // Now, we are done. Notify the main thread that task 1 is complete. 
    [self performSelectorOnMainThread:@selector(nofityDone:) withObject:[NSNumber numberWithInt:1] waitUntilDone:YES]; 
    // Move onto the next task once the main thread is done handling the notification 
    [self action2]; 
} 
-(void)action2 
{ 
    // Do the same sort of thing as "action1" did, then call he next method 
} 
+0

Спасибо, но это нецелесообразно для этого решения. – jarryd

Смежные вопросы