2013-03-13 42 views
4

我有許多任務需要串行執行,但任務包括完成塊中的下一個塊。序列化異步方法

什麼是一次完成這些任務的好技術,在當前完成其完成塊之後開始下一個任務?

是否有一種技術,而不是NSOperation子類與串行NSOperationQueue?

+0

他們全部NSOperations? – TheJer 2013-03-13 22:40:13

+0

你不想子類NSOperation嗎?或者你有反對串行'NSOperationQueue'? – Rob 2013-03-13 22:55:34

+0

它們使用addOperationWithBlock作爲塊添加。異步方法不會等待,因此隊列上的併發1不會執行任何操作。 – jarryd 2013-03-13 22:55:58

回答

6

標準溶液:

  1. NSOperationQueue1maxConcurrentOperationCount。你說你不想這麼做,但你不知道爲什麼。串行隊列是最合乎邏輯的解決方案。

    例如:

    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. 您還可以創建一個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"); 
    }); 
    
+1

謝謝。問題是我使用addOperationWithBlock添加方法調用,但是因爲它們是異步方法,所以即使併發性設置爲1,也會出現「操作無法完成,打開的文件過多」的錯誤,塊被標記爲因異步呼叫未被等待而結束。 – jarryd 2013-03-13 22:55:13

+0

@ Helium3你可以用你調度到背景的代碼的性質來更新你的問題嗎?當排隊的操作本身是異步的時候,有不同的方法,但是如果你可以更具體一些,這會有所幫助。在我的文件下載器類中,我將NSOperation子類化,並且在下載完成之前不要設置「isFinished」,但我不想繼續猜測你想要做什麼。 – Rob 2013-03-13 23:00:52

+0

@ Helium3除了子類化'NSOperation'和手工控制何時設置'isFinished'之外,您還可以爲每個文件創建兩個操作,一個是異步操作的開始,另一個是異步操作的完成處理程序。您可以根據前一個操作完成下一個操作。有關示例,請參閱http://stackoverflow.com/questions/14195706/multiple-locations-in-google-map-mkmapitem/14198584#14198584。 – Rob 2013-03-13 23:06:04

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 
} 
+0

謝謝,但這對於此解決方案並不實用。 – jarryd 2013-03-13 22:49:36