Serializing Asynchronous Methods

I have a number of tasks that I need to perform sequentially, but the task includes the next block in the completion block.

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

Is there a method other than a subclass of NSOperation with a sequential NSOperationQueue?

+4
source share
3 answers

Standard solutions:

  • NSOperationQueue with maxConcurrentOperationCount of 1 . You say you do not want to do this, but you do not say why. Serial queues are the most logical solution.

    For instance:

     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"); }]; 
  • If you do not want a serial NSOperationQueue , you can use the standard parallel queue, but just make each operation depend on the previous one. You will achieve the consistent behavior that you are looking for without using a sequential queue.

    For instance:

     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]; 
  • You can also create a sequential GCD queue with dispatch_queue_create . It does the same thing as the first option, except for using a GCD instead of an NSOperationQueue .

    For instance:

     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"); }); 
+6
source

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

+1
source

Something like that:

 -(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
source

Source: https://habr.com/ru/post/1469099/


All Articles