序列化异步方法

时间:2013-03-13 22:36:06

标签: ios block

我需要执行许多串行执行的任务,但任务包括完成块中的下一个块。

一次执行这些任务的好方法是什么,在当前完成其完成块之后开始下一个任务?

是否有一种非NSOperation子类的技术与序列NSOperationQueue?

3 个答案:

答案 0 :(得分:7)

标准解决方案:

  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序列队列。它实现了与第一个选项相同的功能,除了使用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 :(得分:1)

我认为这是一个有趣的解决方案:https://github.com/berzniz/Sequencer

答案 2 :(得分: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
}