Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing asynchronous methods

Tags:

ios

block

I have a number of tasks I need to execute serially but the task includes next block in a completion block.

What is a good technique for doing these tasks one at a time, starting the next task after the current one completes its completion block?

Is there a technique other than a NSOperation subclass with a serial NSOperationQueue?

like image 440
some_id Avatar asked Mar 13 '13 22:03

some_id


2 Answers

Standard solutions:

  1. NSOperationQueue with maxConcurrentOperationCount of 1. You say you don't want to do that, but you don't say why. Serial queues are the most logical solution.

    For example:

    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. If you don't want a serial NSOperationQueue, you can use a standard concurrent queue, but just make each operation dependent upon the prior one. You'll achieve the serial behavior you're looking for without using a serial queue.

    For example:

    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. You could also create a GCD serial queue with dispatch_queue_create. It achieves the same thing as the first option, except using GCD instead of NSOperationQueue.

    For example:

    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");
    });
    
like image 65
Rob Avatar answered Oct 24 '22 11:10

Rob


I think this is an interesting solution: https://github.com/berzniz/Sequencer

like image 41
Blake Schwendiman Avatar answered Oct 24 '22 12:10

Blake Schwendiman