我需要执行许多串行执行的任务,但任务包括完成块中的下一个块。
一次执行这些任务的好方法是什么,在当前完成其完成块之后开始下一个任务?
是否有一种非NSOperation子类的技术与序列NSOperationQueue?
答案 0 :(得分:7)
标准解决方案:
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");
}];
如果您不需要序列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];
您还可以使用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
}