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++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. 今天讲一个小点,虽然小,但如果没有 ...
随机推荐
- Microsoft Edge 首个 Chromium 内核版释出
翻译功能释出 navigator.userAgent"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, ...
- Linux下安装桌面
1. 安装之前先测试是否有桌面 2. 建立yum源文件 3. 挂载好光盘(/rhel自己创建) 4. 使用yum list 查看 ...
- github踩坑之git命令收集与整理(windows)
最近开始又捡起git,第一家公司用的就是git,一直掌握的也不深刻,就知道常用的几个命令,虽然现在用svn,但是觉得git还是不能丢,遂又捡起来了.先总结一部分目前练习用到的,慢慢填补吧~ githu ...
- Run-time type information--RTTI
In computer programming, run-time type information or run-time type identification (RTTI)[1] refers ...
- js浏览器问题
前段时间做了个项目,里面关于手机移动端下载的问题 开始是判断微信.ios和android系统的下载 因为微信屏蔽点击事件和链接的缘故,需要通过打开新页面来进行下载 ios和android的下载分别为不 ...
- 使用easyui combobox初始化+在input中触发下拉框+获取值
效果图: 1.html <input id="alarmLeve" class="easyui-combobox" name="alarmLev ...
- POJ 3122 Pie( 二分搜索 )
链接:传送门 题意:一个小朋友开生日派对邀请了 F 个朋友,排队上有 N 个 底面半径为 ri ,高度为 1 的派,这 F 个朋友非常不友好,非得"平分"这些派,每个人都不想拿到若 ...
- vue 根据下拉框动态切换form的rule
taskCategorySelect (val) { // 任务类别下拉选择 if ( val == 5 ) { this.cameraORgateway = false; // true不可以使用 ...
- [LeetCode] 242. 有效的字母异位词 valid-anagram(排序)
注意这里字母异位词的定义是:字母类别及个数都要一样,只是排列顺序不同. class Solution(object): def isAnagram(self, s, t): ""& ...
- Ubuntu下安装curl和corn
Ubuntu下安装curl sudo apt install curl Ubuntu下安装cron apt-get install cron