2015-06-03 90 views
1

我想在後臺線程上按順序完成一些操作。當完成塊成功時,NSOperationQueue添加新操作

我調用的函數已經有一個完成塊,所以當函數完成時我想用一個新的參數調用同一個函數。

所以基本上是連續的操作。

dispatch_asyncDISPATCH_QUEUE_SERIAL,以正確的順序觸發功能,但不關心在調用下一個功能之前第一個功能是否完成,所以我不想使用它們。

NSOperationQueue* serialQ = [[NSOperationQueue alloc] init]; serialQ.maxConcurrentOperationCount = 1;對我更有意義。所以當第一個函數開始計算隊列中的第二個函數時,必須等到它完成它的完成塊。

NSOperationQueue* serialQ = [[NSOperationQueue alloc] init]; 
    serialQ.maxConcurrentOperationCount = 1; //this will set this queue to Serial 



     for (File *file in queueArrray) { 
      Streamer *streamer=[[Streamer alloc] init]; 

      NSBlockOperation *downloadOperation = [[NSBlockOperation alloc] init]; 

      __weak NSBlockOperation *weakDownloadOperation = downloadOperation; 

      [weakDownloadOperation addExecutionBlock:^{ 
       [streamer loadFile:file withCallback:^(NSString *error, BOOL success) { 
        if (success) { 
         NSLog(@"file loaded %@",file.fileUrl); 
         //here start the next operation !!!!!!!! 
         ?????????????????????????????????????? 
        } 
       }]; 
      }]; 
     } 

回答

1

您的目標方法是異步的。這意味着你不能使用普通塊操作,你需要創建一個自定義操作子類,以便在異步方法完成之前操作不會結束。

搜索谷歌的例子創建異步操作子類的例子,因爲有幾件事你需要組織。

另外,你可以有一個文件數組(或任何)的東西,每次你的異步方法完成檢查是否有anyyhing那裏,刪除第一個項目,並處理它。這將繼續,直到陣列爲空...

2

串行隊列infact確保在第二個塊執行之前,添加到隊列中的第一個塊執行完成。

-(void)testSerialQueue 
{ 
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL); 

    dispatch_async(serialQueue, ^{ 
     [self countTo100]; 
    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom200To400]; 
    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom400To500]; 
    }); 

} 

- (void)countTo100 
{ 
    for (int i = 0; i < 100; i++) { 
     NSLog(@"%d", i); 
    } 
} 

- (void)countFrom200To400 
{ 
    for (int i = 200; i < 400; i++) { 
     NSLog(@"%d", i); 
    } 
} 

- (void)countFrom400To500 
{ 
    for (int i = 400; i < 500; i++) { 
     NSLog(@"%d", i); 
    } 
} 

如果你看看日誌從上面它將從0連續打印.. 100先200 ... 400和400 ... 500

現在,考慮下面的代碼片段,在那裏你執行每個方法併發塊內等,

-(void)testSerialQueue 
{ 
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL); 

    dispatch_async(serialQueue, ^{ 
     [self countTo100]; 
    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom200To400]; 
    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom400To500]; 
    }); 

} 

- (void)countTo100 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 0; i < 100; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 

} 

- (void)countFrom200To400 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 200; i < 400; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 
} 

- (void)countFrom400To500 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 400; i < 500; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 
} 

在這裏,你添加的所有串行隊列中,但本身的併發塊運行方法中的方法。所以,在這種情況下結果是隨機的。你也可以序列,使用dispatch_group這樣,

-(void)testSerialQueue 
{ 
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL); 

    self.group = dispatch_group_create(); 

    dispatch_async(serialQueue, ^{ 
     [self countTo100]; 
    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom200To400]; 

    }); 

    dispatch_async(serialQueue, ^{ 
     [self countFrom400To500]; 
    }); 
} 

- (void)countTo100 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 0; i < 100; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 
} 

- (void)countFrom200To400 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 200; i < 400; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 

- (void)countFrom400To500 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 400; i < 500; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 

    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 

在這裏,你將再次看到它打印記錄有序。因此,dispatch_group用於序列化併發操作。您可能更願意在此時刪除serialQueue中的dispatch_async。

現在,操作隊列,讓我們看看簡單的例子,

-(void)testSerialQueue 
{ 
    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init]; 

    [operation1 addExecutionBlock:^{ 
     [self countTo100]; 
    }]; 

    [operation2 addExecutionBlock:^{ 
     [self countFrom200To400]; 
    }]; 

    [operation3 addExecutionBlock:^{ 
     [self countFrom400To500]; 
    }];   
} 

- (void)countTo100 
{ 
    for (int i = 0; i < 100; i++) { 
     NSLog(@"%d", i); 
    } 
} 

- (void)countFrom200To400 
{ 
    for (int i = 200; i < 400; i++) { 
     NSLog(@"%d", i); 
    } 
} 

- (void)countFrom400To500 
{ 
    for (int i = 400; i < 500; i++) { 
     NSLog(@"%d", i); 
    } 
} 

計數方法是加入NSOperationQueue與maxConcurrentOperation爲「1」現在更像一個串行隊列。每種方法都不會產生其他一些隊列,所以計數在同一個串行隊列上執行。所以,他們都打印有序。

現在,讓我們看一個模擬您的案例的例子。

-(void)testSerialQueue 
{ 
    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init]; 

    [operation1 addExecutionBlock:^{ 
     [self countTo100]; 
    }]; 

    [operation2 addExecutionBlock:^{ 
     [self countFrom200To400]; 
    }]; 

    [operation3 addExecutionBlock:^{ 
     [self countFrom400To500]; 
    }];   
} 

- (void)countTo100 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 0; i < 100; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 

} 

- (void)countFrom200To400 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 200; i < 400; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 
} 

- (void)countFrom400To500 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 400; i < 500; i++) { 
      NSLog(@"%d", i); 
     } 
    }); 
} 

在這種使用情況下,您可以添加操作到NSOperationQueue(即串行隊列),但再次,在一些其他併發隊列運行單個方法。所以,執行順序是非常隨機的。現在,您可以像使用串行隊列一樣使用dispatch_group解決此問題。

-(void)testSerialQueue 
{ 
    self.group = dispatch_group_create(); 

    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init]; 
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init]; 

    [operation1 addExecutionBlock:^{ 
     [self countTo100]; 
    }]; 

    [operation2 addExecutionBlock:^{ 
     [self countFrom200To400]; 
    }]; 

    [operation3 addExecutionBlock:^{ 
     [self countFrom400To500]; 
    }];   
} 

- (void)countTo100 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 0; i < 100; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 
} 

- (void)countFrom200To400 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 200; i < 400; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 

- (void)countFrom400To500 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 400; i < 500; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 

    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 

現在,你會看到計數再次有序。這是因爲dispatch_group等待每個異步任務完成。

爲您的特定的使用情況,您可以使用循環調用一些方法,像這樣創造NSInvocationOperation,

-(void)testSerialQueue 
{ 
    self.group = dispatch_group_create(); 

    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
    queue.maxConcurrentOperationCount = 1; 


    NSArray *selectors = @[@"countTo100", @"countFrom200To400", @"countFrom400To500"]; 

    for (NSString *selector in selectors) { 
     NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                       selector:NSSelectorFromString(selector) 
                        object:nil]; 
     [queue addOperation:operation]; 
    } 

} 

- (void)countTo100 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 0; i < 100; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 
} 

- (void)countFrom200To400 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 200; i < 400; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 
    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 

- (void)countFrom400To500 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_group_enter(self.group); 

    dispatch_async(concurrentQueue, ^{ 
     for (int i = 400; i < 500; i++) { 
      NSLog(@"%d", i); 
     } 
     dispatch_group_leave(self.group); 

    }); 
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER); 

} 
0

您可以使用信號燈等待,直到功能完成,如果成功與爭論再次調用它。

相關問題