dispatch_group_t踩过的坑
如果想在dispatch_queue中所有的任务执行完成后在做某种操作,在串行队列中,可以把该操作放到最后一个任务执行完成后继续,但是在并行队列中怎么做呢。这就有dispatch_group 成组操作。
有一个需求是,是想发出三个网络请求,当三个请求全部执行返回结果的时候再做一些操作,不论返回的是失败还是成功都算返回结果。
下面是dispatch_group异步并行执行网络请求。
执行完三个异步成组发送请求全部结束后进入到dispatch_group_notify执行最终的那个操作,但是这个时候可以看一下打印结果:
_responseGetVisaGetDianPingList = nil这个你就当做是不为nil的,因为是我为了测试故意置为nil的。我们暂且关注_responseGetVisaDetail = nil,其实这里置为nil是因为成组操作的第一个操作还没有执行结束,不是因为结束了返回失败所以是nil,这个大家不要混淆。正常来说我们想要的结果是,三个请求网络请求执行结束的时候才进入dispatch_group_notify,并且三个response都应该是不为nil有值的。我来解释下,这里为什么到dispatch_group_notify了,但是第一个请求还没有返回结束,这是因为上面这种写法遵守的成组全部执行结束指的是三个block写的代码直观进行执行完就不算了,不包含block内部的异步请求,因此会出现这中间结果。所以我们应该换一种写法。下图:
这种dispatch_group_enter和dispatch_group_leave是成对出现的,当进入一个操作后,在适当的位置加上dispatch_group_leave,比如在这里,进入第一个enter执行requestGetVisaDetail操作,那么紧跟的这个block,是当执行结束(成功或失败)后会立刻执行,是真正关注包含了异步的情况,所以这里当执行到断点的时候,结果如下是正确的:
_responseGetVisaGetDianPingList = nil这个忽略,其他的都是正常的。验证正确,因此在成组加载异步请求的时候一定到区分开。避免入坑。
今天16年7月9号,又发现了一个坑,在这里做一个解释。
其实这种成组一共3个的发送请求,执行到dispatch_group_notify的时候,前面三个请求必然全部请求有结果了才执行到了这里,但是呢,之前一直有个点理解错了,之前一直以为第一个请求发送有结果了,才去执行第二个请求,接着同样,但是呢,就是因为这个理解失误才导致问题。其实实际上是这样执行的,当第一个请求发出去之后,因为是异步,第二个请求不会等到第一个请求有结果了才去发送第二个请求,第二个dispatch_group_enter和dispatch_group_leave之间的[self requestCrossRecommoned]仍然会执行,所以第三个请求也是不会因为等到第一个和第二个请求有结果了才去执行请求,但是呢问题来了,因为第三个请求会有两个请求参数是第一个请求的结果response的字段,这样就会有问题啦,因为当第三个请求发起的时候这个时候,第一个请求一般情况下都是没有返回结果的,还没请求结束,这样第三个请求的请求参数会为nil,导致结果和预期的不一致。那么怎么解决的呢?就是把第三个请求放到第一个请求结束,有结果之后,我是把它放到第一个请求结束成功里面了,这样虽然第二个请求有可能是第一个执行结束的,第一个第二个执行结束有结果,因为第三个请求放在第二个结果结束的成功response里面,所以是最后一个发起的,但是呢,这个时候第三个请求参数是存在的。因此问题解决,三个请求全部执行结束,才会走dispatch_group_notify。其实在这个解决方案之前,我是单单把第三个请求[self requestCrossRecommoned]放到第一个请求里面的,没有用dispatch_group_enter和dispatch_group_leave包装起来,所以会导致当执行到dispatch_group_notify的时候,第三个请求还没有执行结束还没有结果。所以我猜想啊,这个dispatch_group_enter和dispatch_group_leave只会保证一个方法内部的请求执行结束,并不会保证里面再有一层的请求结束才执行dispatch_group_notify。
下面是解决后的方案,把grouop传到第一个请求方法里面,作为第三个请求的包装。
下面一张图就是放在第一个请求的执行结束的成功response里面,并且用dispatch_group_enter和dispatch_group_leave包了起来,这样可以保证dispatch_group_notify执行起必须是这三个请求全部执行结束。
dispatch_group_t踩过的坑的更多相关文章
- 项目中踩过的坑之-sessionStorage
总想写点什么,却不知道从何写起,那就从项目中踩过的坑开始吧,希望能给可能碰到相同问题的小伙伴一点帮助. 项目情景: 有一个id,要求通过当前网页打开一个新页面(不是当前页面),并把id传给打开的新页面 ...
- web开发实战--弹出式富文本编辑器的实现思路和踩过的坑
前言: 和弟弟合作, 一起整了个智慧屋的小web站点, 里面包含了很多经典的智力和推理题. 其实该站点从技术层面来分析的话, 也算一个信息发布站点. 因此在该网站的后台运营中, 富文本的编辑器显得尤为 ...
- "开发路上踩过的坑要一个个填起来————持续更新······(7月30日)"
欢迎转载,请注明出处! https://gii16.github.io/learnmore/2016/07/29/problem.html 踩过的坑及解决方案记录在此篇博文中! 个人理解,如有偏颇,欢 ...
- 【转载】Fragment 全解析(1):那些年踩过的坑
http://www.jianshu.com/p/d9143a92ad94 Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使 ...
- Redis Cluster踩过的坑
Redis Cluster踩过的坑请参考如下链接:http://www.iteye.com/blogs/subjects/Redis_Cluster_Devops
- 第八篇:web之前端踩的一些坑
前端踩的一些坑 前端踩的一些坑 本节内容 事件代理 清除标签的所有事件 bootstrap的模态框自定义方法 ajax在django里面实现post提交 ajax提交数据嵌套 1.事件代理 之前写 ...
- 使用ffmpeg视频编码过程中踩的一个坑
今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果: ...
- 那些年踩过的坑之:first-child伪类选择器
原文:那些年踩过的坑之:first-child伪类选择器 :first-child 选择器用于选取属于其父元素的首个子元素的指定选择器.——w3school 嗯,乍一看好像说的不是很明白,因此这个选择 ...
- 《C++之那些年踩过的坑(二)》
C++之那些年踩过的坑(二) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. 今天讲一个小点,虽然小,但如果没有 ...
随机推荐
- android UI卡顿问题学习
转自https://blog.csdn.net/joye123/article/details/79425398 https://blog.csdn.net/zhenjie_chang/article ...
- MySQL 5.6.26 通过frm & ibd 恢复数据过程
在A服务器上创建数据库yoonroot(yoon)> show create table yoon\G*************************** 1. row *********** ...
- UNP学习笔记4——I/O复用:select和poll函数
1 概述 之间的学习中发现,传统的阻塞式系统调用不仅浪费进程运行时间,而且会带来狠毒问题.因此进程需要有一种预先告知内核的能力,使得内核一旦发现进程指定的一个或者多个I/O条件就绪,它就通知进程.这个 ...
- 结构化编程-Structured programming
结构话编程强调的是对流程的控制: 它为面向过程编程提供天然的支持. Structured programming is a programming paradigm aimed at improvin ...
- mysql定时清理binlog
一.没有主从同步的情况下清理日志 mysql -uroot -p123456 -e 'PURGE MASTER LOGS BEFORE DATE_SUB( NOW( ),INTERVAL 5 DAY) ...
- node——try-catch与异步操作
//try-catch,用于捕获异常 //try-catch在node中只能捕获同步的异常,不能捕获异步异常 var fs=require('fs'); /*fs.writeFile('./abc.t ...
- 说说Shell在代码重构中的应用
说说Shell在代码重构中的应用 出处信息 出处:http://blogread.cn/it/article/3426?f=wb 代码重构(Code refactoring)有时是很枯燥的,字符 ...
- [学习笔记] CS131 Computer Vision: Foundations and Applications:Lecture 9 深度学习
深度学习 So far this week Edge detection RANSAC SIFT K-Means Linear classifier Mean-shift PCA/Eigenfaces ...
- Redis:持久化之RDB和AOF
Redis:持久化之RDB和AOF RDB(Redis DataBase) 在指定的时间间隔内将内存中的数据集快照写入硬盘 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里. R ...
- List<T>与List<?>的区别
T 代表某一类型 ? 代表任意类型.. T因为代表是某一确定类型..所以你可以使用它..比如你有个List<T>类型的变量tList 你可以用T t = tList.get(1);也可以用 ...