Serializing asynchronous methods

让人想犯罪 __ 提交于 2019-12-18 13:31:21

问题


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?


回答1:


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



回答2:


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




回答3:


What about something like this:

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


来源:https://stackoverflow.com/questions/15397848/serializing-asynchronous-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!