我有許多任務需要串行執行,但任務包括完成塊中的下一個塊。序列化異步方法
什麼是一次完成這些任務的好技術,在當前完成其完成塊之後開始下一個任務?
是否有一種技術,而不是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