多个异步任务, 网络请求之间互相依赖, 请求本身也是异步, 如何让所有网络请求数据返回后才继续执行任务
1.到这里其实有两层异步, 首先是任务是异步执行
的, 任务里的代码只要执行完毕, 任务就算执行完成
2.网络请求
也是异步
执行, 请求的数据不会立刻返回, 我们要求的是 请求的数据返回之后才算任务结束
3.到这里应该大概知道问题点了 show me the code
未同步结果的情况
-(void)test1
{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
NSURLSession *session = [NSURLSession sharedSession];
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求1 返回数据");
}];
[task resume];
NSLog(@"请求1 ");
});
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求2 返回数据");
}];
[task resume];
NSLog(@"请求2 ");
});
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求3 返回数据");
}];
[task resume];
NSLog(@"请求3 ");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"请求全部完成");
});
}
2022-12-20 12:02:18.600424+0800 异步多个网络请求同步返回问题[56505:9936064] 请求3
2022-12-20 12:02:18.600425+0800 异步多个网络请求同步返回问题[56505:9936062] 请求1
2022-12-20 12:02:18.600427+0800 异步多个网络请求同步返回问题[56505:9936063] 请求2
2022-12-20 12:02:18.600508+0800 异步多个网络请求同步返回问题[56505:9936063] 请求全部完成
2022-12-20 12:02:18.703725+0800 异步多个网络请求同步返回问题[56505:9936062] 请求2 返回数据
2022-12-20 12:02:18.742708+0800 异步多个网络请求同步返回问题[56505:9936064] 请求1 返回数据
2022-12-20 12:02:18.743819+0800 异步多个网络请求同步返回问题[56505:9936069] 请求3 返回数据
- 从代码打印结果来看
请求1.2.3 只要执行完毕, 就打印了全部完成
, 这不符合预期 - 我们要的是
请求1.2.3 数据都返回后才算 全部完成
- 我们可以通过
dispatch_group_enter(group)
和dispatch_group_leave(group)
更加精准的控制
简单来说dispatch_group_enter
就是 对group内部计数 + 1
,dispatch_group_leave
就是对计数-1
, 有点类似于retain 和 release
, 它们是成对出现, 以前的做法是自己维护一个计数, 在对比计数和总数是否匹配, 匹配就相当于网络请求全部完成, 使用dispatch_group_enter看起来会更加规范
-(void)test2
{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
NSURLSession *session = [NSURLSession sharedSession];
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求1 返回数据");
dispatch_group_leave(group);
}];
[task resume];
NSLog(@"请求1 ");
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求2 返回数据");
dispatch_group_leave(group);
}];
[task resume];
NSLog(@"请求2 ");
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求3 返回数据");
dispatch_group_leave(group);
}];
[task resume];
NSLog(@"请求3 ");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"请求全部完成");
});
}
2022-12-20 12:13:57.242873+0800 异步多个网络请求同步返回问题[58688:9949703] 请求1
2022-12-20 12:13:57.242875+0800 异步多个网络请求同步返回问题[58688:9949705] 请求3
2022-12-20 12:13:57.242877+0800 异步多个网络请求同步返回问题[58688:9949709] 请求2
2022-12-20 12:13:57.353102+0800 异步多个网络请求同步返回问题[58688:9949709] 请求3 返回数据
2022-12-20 12:13:57.393535+0800 异步多个网络请求同步返回问题[58688:9949704] 请求2 返回数据
2022-12-20 12:13:57.403210+0800 异步多个网络请求同步返回问题[58688:9949708] 请求1 返回数据
2022-12-20 12:13:57.403299+0800 异步多个网络请求同步返回问题[58688:9949703] 请求全部完成
多个异步任务, 网络请求之间互相依赖, 请求本身也是异步, 比如c依赖b, b依赖a 可以使用dispatch_semaphore_t
-(void)test3
{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
NSURLSession *session = [NSURLSession sharedSession];
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求a 返回数据");
dispatch_semaphore_signal(semaphore);
}];
[task resume];
NSLog(@"请求a");
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求b 返回数据");
dispatch_semaphore_signal(semaphore);
}];
[task resume];
NSLog(@"请求b ");
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"请求c 返回数据");
dispatch_semaphore_signal(semaphore);
}];
[task resume];
NSLog(@"请求c ");
});
}
2022-12-20 12:27:55.905315+0800 异步多个网络请求同步返回问题[61308:9965813] 请求a
2022-12-20 12:27:56.013479+0800 异步多个网络请求同步返回问题[61308:9965819] 请求a 返回数据
2022-12-20 12:27:56.013689+0800 异步多个网络请求同步返回问题[61308:9965814] 请求b
2022-12-20 12:27:56.023961+0800 异步多个网络请求同步返回问题[61308:9965814] 请求b 返回数据
2022-12-20 12:27:56.024199+0800 异步多个网络请求同步返回问题[61308:9965815] 请求c
2022-12-20 12:27:56.033318+0800 异步多个网络请求同步返回问题[61308:9965813] 请求c 返回数据
- 总结来说就使用下面两种来解决
1.dispatch_group_enter(), dispatch_group_level
2.dispatch_semaphore_t
网友评论