问题描述:MBProgressHUD是一个流行的第三方库,一般用于展示进度菊花。
常用的有show,和hide方法;
以下为一个常用的使用模式:
1、先GCD主线程调用show方法;
2、开启GCD支线程执行耗时操作doSomething();
3、doSomething()耗时操作结束的回调中,再次在主线程调用hide方法;
1 2 3 4 5 6 7 8 9 10 |
dispatch_async(dispatch_get_main_queue(), ^{ [hud show:YES]; }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ [self doSomething:^{ dispatch_async(dispatch_get_main_queue(), ^{ [hud hide:YES]; }); }]; }); |
这样一般情况下不会有问题,至少我还没遇到;
当逻辑复杂了,有的同学把这段代码放进了一个函数。但使用调用这个函数的时候又多余的使用了一次主线程
1 2 3 4 5 6 7 8 9 10 |
dispatch_async(dispatch_get_main_queue(), ^{ [hud show:YES]; }); //在主线程外面又调了一次主线程 //就等于写成了这样 dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{ [hud show:YES]; }); }); |
这时doSomething这个耗时操作执行很短的时候,就会出现:
hud在主线程尚未显示,doSomething在支线程已经执行完成,回调隐藏hud;
然后hud显示出来,这时hud缺少了配对的hide函数,就一直执行下去了。
这个时间延迟与队列中的任务数有关,如果你有很多界面刷新任务要做,而这个任务时长大于了你的doSomething耗时,就会有问题;如果耗时操作doSomething大于一定时长,两个get_main_queue带来的队列延时不会造成出错;
结论:
使用GCD时,保持线程的干净,不用太多层层嵌套;
耗时操作太短时,要加锁保证回调进到任务队列中的位置;