关于这个问题,网上的教程很多,其中绝大多数都没有讲到在实际使用过程中会遇到的坑。所以,在使用之初可能会遇到一些困惑。比如:我明明已经按照给出的教程实现相关任务,为什么不是预想的结果呢?(想要最后执行的任务却不是最后执行,同步任务这里不予考虑)
使用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()
必须配套使用。
写在最后:或许还存在其他的问题吧?欢迎补充!万分感谢!