關于這個問題,網(wǎng)上的教程很多,其中絕大多數(shù)都沒有講到在實際使用過程中會遇到的坑。所以,在使用之初可能會遇到一些困惑。比如:我明明已經(jīng)按照給出的教程實現(xiàn)相關任務,為什么不是預想的結果呢?(想要最后執(zhí)行的任務卻不是最后執(zhí)行,同步任務這里不予考慮)
使用GCD實現(xiàn)多個任務完成再執(zhí)行另一任務的常見方法形如:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 任務A
dispatch_group_async(group, globalQueue, ^{
sleep(5);
NSLog(@"A");
});
// 任務B
dispatch_group_async(group, globalQueue, ^{
NSLog(@"B");
});
// 任務over
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"over");
});
在上面的方法中,運行結果是 B->A->over。簡直完美!看起來沒有問題啊,我甚至是讓A睡了5秒鐘,任務over還是最后執(zhí)行。但。。。但是,為什么實際開發(fā)過程中,就會出現(xiàn)問題呢?
來看看出問題的一個例子:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 任務A
dispatch_group_async(group, globalQueue, ^{
sleep(2);
NSLog(@"A");
// 任務C
dispatch_async(globalQueue, ^{
sleep(5);
NSLog(@"C");
});
});
// 任務B
dispatch_group_async(group, globalQueue, ^{
NSLog(@"B");
// 任務D
dispatch_async(globalQueue, ^{
sleep(2);
NSLog(@"D");
});
});
// 任務over
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"over");
});
它的執(zhí)行結果為:B->D->A->over->C。??為什么呢?因為任務C/D不歸調(diào)度組管啊。那我們把它加入調(diào)度組呢?
代碼變成了這樣:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 任務A
dispatch_group_async(group, globalQueue, ^{
sleep(2);
NSLog(@"A");
// 任務C
dispatch_group_async(group, globalQueue, ^{
sleep(5);
NSLog(@"C");
});
});
// 任務B
dispatch_group_async(group, globalQueue, ^{
NSLog(@"B");
// 任務D
dispatch_group_async(group, globalQueue, ^{
sleep(2);
NSLog(@"D");
});
});
// 任務over
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"over");
});
執(zhí)行結果為:B->A->D->C->over。這樣以來,結果就是我們想要的了。任務over是最后執(zhí)行的。然而,事情還沒完。想象一下,我們要做一個網(wǎng)絡請求,比如使用AFN。把任務C、D換成兩個異步網(wǎng)絡請求,這個時候,就沒法使用上述方法把任務C/D加入調(diào)度組,因為AFN自己管理多線程任務了。怎么辦呢?
可以嘗試這么搞:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 任務A
dispatch_group_async(group, globalQueue, ^{
sleep(2);
NSLog(@"A");
// 任務C
dispatch_group_enter(group);
dispatch_async(globalQueue, ^{
sleep(5);
NSLog(@"C");
dispatch_group_leave(group);
});
});
// 任務B
dispatch_group_async(group, globalQueue, ^{
NSLog(@"B");
// 任務D
dispatch_group_enter(group);
dispatch_async(globalQueue, ^{
sleep(2);
NSLog(@"D");
dispatch_group_leave(group);
});
});
// 任務over
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"over");
});
在block之前入組,在block執(zhí)行完成后出組。dispatch_group_enter()和 dispatch_group_leave()必須配套使用。
寫在最后:或許還存在其他的問題吧?歡迎補充!萬分感謝!