GCD實現(xiàn)多個任務完成后再執(zhí)行某一任務的正確姿勢

關于這個問題,網(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()必須配套使用。

寫在最后:或許還存在其他的問題吧?歡迎補充!萬分感謝!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • NSThread 第一種:通過NSThread的對象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 955評論 0 3
  • 改變,難嗎? 要改變現(xiàn)狀,首先要改變自己;要改變自己,首先要改變自己對問題的看法。在《高效能人士的七個習慣》中看到...
    Manjusaka_m閱讀 70評論 0 0
  • 摘錄: 1.文明社會這樣消磨自己的心智,把短促的生命浪費在無聊的應酬上實在令人費解。 2.它使人想到一條平靜的小河...
    狐貍的帽子閱讀 365評論 0 0
  • 兩千多年前的莊周做了一個夢,夢見一只蝴蝶。莊公為何夢蝶?總是莊公默默地想著蝶的,蝶才會進入莊公夢里。 可是,夢里的...
    依蘭襲香閱讀 1,117評論 1 2

友情鏈接更多精彩內(nèi)容