我有许多任务需要串行执行,但任务包括完成块中的下一个块。序列化异步方法
什么是一次完成这些任务的好技术,在当前完成其完成块之后开始下一个任务?
是否有一种技术,而不是NSOperation子类与串行NSOperationQueue?
我有许多任务需要串行执行,但任务包括完成块中的下一个块。序列化异步方法
什么是一次完成这些任务的好技术,在当前完成其完成块之后开始下一个任务?
是否有一种技术,而不是NSOperation子类与串行NSOperationQueue?
标准溶液:
NSOperationQueue
与1
maxConcurrentOperationCount
。你说你不想这么做,但你不知道为什么。串行队列是最合乎逻辑的解决方案。
例如:
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];
您还可以创建一个GCD串行队列dispatch_queue_create
。除了使用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");
});
谢谢。问题是我使用addOperationWithBlock添加方法调用,但是因为它们是异步方法,所以即使并发性设置为1,也会出现“操作无法完成,打开的文件过多”的错误,块被标记为因异步呼叫未被等待而结束。 – jarryd 2013-03-13 22:55:13
@ Helium3你可以用你调度到背景的代码的性质来更新你的问题吗?当排队的操作本身是异步的时候,有不同的方法,但是如果你可以更具体一些,这会有所帮助。在我的文件下载器类中,我将NSOperation子类化,并且在下载完成之前不要设置“isFinished”,但我不想继续猜测你想要做什么。 – Rob 2013-03-13 23:00:52
@ Helium3除了子类化'NSOperation'和手工控制何时设置'isFinished'之外,您还可以为每个文件创建两个操作,一个是异步操作的开始,另一个是异步操作的完成处理程序。您可以根据前一个操作完成下一个操作。有关示例,请参阅http://stackoverflow.com/questions/14195706/multiple-locations-in-google-map-mkmapitem/14198584#14198584。 – Rob 2013-03-13 23:06:04
什么是这样的:
-(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
}
谢谢,但这对于此解决方案并不实用。 – jarryd 2013-03-13 22:49:36
我觉得这是一个有趣的解决方案:https://github.com/berzniz/Sequencer
他们全部NSOperations? – TheJer 2013-03-13 22:40:13
你不想子类NSOperation吗?或者你有反对串行'NSOperationQueue'? – Rob 2013-03-13 22:55:34
它们使用addOperationWithBlock作为块添加。异步方法不会等待,因此队列上的并发1不会执行任何操作。 – jarryd 2013-03-13 22:55:58