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++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. 今天讲一个小点,虽然小,但如果没有 ...
随机推荐
- GCC中的弱符号与强符号
GCC中的弱符号与强符号 我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候将会出现符号重复定义的错误.比如我们在目标文件A和目标文件B都 ...
- shell脚本切割tomcat日志文件
转自:http://www.cnblogs.com/lishun1005/p/6054816.html 鉴于在调试logback和log4j的文件切割一直无法成功,随性用shell写个脚本用来切割to ...
- systemd bug: bz1437114 core:execute: fix fork() fail handling in exec_spawn()
问题现象 大量僵尸进程 root 32278 0.0 0.0 0 0 ? Z 05:39 0:00 [runuser] <defunct> root 32280 0.0 0.0 0 0 ? ...
- u-boot启动代码start.S详解
(1)定义入口.由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本 ...
- Python-基础-day4
深浅copy 1.先看赋值运算 h1 = [1,2,3,['aihuidi','hhhh']] h2 = h1 h1[0] = 111 print(h1) print(h2) #结果: # [111, ...
- PHP读取XML数据中CDATA内数值
// 在开发过程中遇到对XML获取时候加载 CDATA 无法读取内部的数值(例如微信平台的返回值) $content = simplexml_load_string('<content>& ...
- 关于使用动态语言运行时 (. net)
AutoCAD Managed .NET API允许您使用使用. NET 4.0 引入的动态语言运行时 (DLR). 使用DLR可以直接访问对象, 而无需: 打开一个对象进行读取或写入, 然后在完成后 ...
- 洛谷 1156 dp
洛谷1156 dp 类背包问题 老久没有自己想出来过dp方程了,,,虽然到最后还是只写了30分,,, 设dp[j]表示最大生命值为i时的最大高度,则对于每个物品,可以选择吃掉或者放上去,即转移为dp[ ...
- jquery简直是太酷炫强大了
链接地址:http://www.yyyweb.com/350.html Web 开发中很实用的10个效果[源码下载] 小鱼 发布于 3年前 (2014-07-15) 分类:前端开发 阅读(303741 ...
- soapUI 5.1.2 下载以及破解
转:https://blog.csdn.net/weiqing723/article/details/78865734