GCD实现多个任务完成后再执行某一任务的正确姿势

2017-09-25  本文已影响33人  本源道人

关于这个问题,网上的教程很多,其中绝大多数都没有讲到在实际使用过程中会遇到的坑。所以,在使用之初可能会遇到一些困惑。比如:我明明已经按照给出的教程实现相关任务,为什么不是预想的结果呢?(想要最后执行的任务却不是最后执行,同步任务这里不予考虑)

使用GCD实现多个任务完成再执行另一任务的常见方法形如:

    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还是最后执行。但。。。但是,为什么实际开发过程中,就会出现问题呢?

来看看出问题的一个例子:

    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");
    });

它的执行结果为:B->D->A->over->C。😓为什么呢?因为任务C/D不归调度组管啊。那我们把它加入调度组呢?

代码变成了这样:

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");
    });

执行结果为:B->A->D->C->over。这样以来,结果就是我们想要的了。任务over是最后执行的。然而,事情还没完。想象一下,我们要做一个网络请求,比如使用AFN。把任务C、D换成两个异步网络请求,这个时候,就没法使用上述方法把任务C/D加入调度组,因为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执行完成后出组。dispatch_group_enter()dispatch_group_leave()必须配套使用。

写在最后:或许还存在其他的问题吧?欢迎补充!万分感谢!

上一篇 下一篇

猜你喜欢

热点阅读