有這麼一個需要,分別執行2個耗時的異步操作,等2個異步操作都執行完畢後在回到主線程執行操作。如果想要快速高效地實現這個需求,可以考慮使用調度組。 調度組的創建代碼如下:
dispatch_group_t group = dispatch_group_create();
往調度組裡面添加任務的函數如下:
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, ^(void)block)
第一個參數group是一個調度組,queue是一個異步隊列,這裡如果使用同步隊列意義就不大了,不過還是能達到效果,第三個參數是一個執行代碼塊,任務都添加到該代碼塊裡面。 往調度組裡面添加任務並獲得通知的代碼如下:
// 群組-統一監控一組任務
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 添加任務
// group 負責監控任務,queue 負責調度任務
dispatch_group_async(group, q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"任務1 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任務2 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任務3 %@", [NSThread currentThread]);
});
// 監聽所有任務完成 - 等到 group 中的所有任務執行完畢後,"由隊列調度 block 中的任務異步執行!"
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 修改為主隊列,後台批量下載,結束後,主線程統一更新UI
NSLog(@"OK %@", [NSThread currentThread]);
});
NSLog(@"come here");
代碼的執行結果如下:
其中任務的下載順序以及"come here”出現的地方不確定,但主線程的更新操作總會在最後才執行!
GCD調度組中還有一個添加任務的函數: dispatch_group_enter(dispatch_group_t group) dispatch_group_leave(dispatch_group_t group) 這兩個函數要配對出現 例如:
// 群組-統一監控一組任務
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 1> 入組 -> 之後的 block 會被 group 監聽
// dispatch_group_enter 一定和 dispatch_group_leave 要配對出現
dispatch_group_enter(group);
dispatch_async(q, ^{
NSLog(@"task1 %@", [NSThread currentThread]);
// block 的末尾,所有任務執行完畢後,添加一個出組
dispatch_group_leave(group);
});
// 再次入組
dispatch_group_enter(group);
dispatch_async(q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"task2 %@", [NSThread currentThread]);
// block 的末尾,所有任務執行完畢後,添加一個出組
dispatch_group_leave(group);
});
// 群組結束
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"OVER");
});
NSLog(@"come here");
代碼執行的效果與剛才那種方式相同! GCD中還有一個函數
dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout)
該函數是個阻塞式的等待,當我們將第二個參數設置為DISPATCH_TIME_FOREVER時,群組任務不執行完,後續代碼就會無法執行,也就是說只要任務不執行完come here就不會打印。