我做的一件事是:
-(void)GrabbingProcess:(void (^)())block;
{
self.OtherGrabbingIndicator +=1;
block();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
self.OtherGrabbingIndicator -=1;
});
}
每次我想在后台运行可能需要很长时间的事情时,我会做类似
的事情[Grabclass grab] GrabbingProcess:^ { //做一些事情抓取数据等 }];
有许多这样的功能和许多这样的数据。例如,起初我会抓住所有的商家ID。然后我会在单独的线程中获取有关业务的所有详细信息。
我想知道所有这些线程完成并发布合适通知的时间。
我的解决方案的问题是,经过一段时间后,即使所有这些线程都已完成,self.OtherGrabbingIndicator在2或3左右徘徊的价值也经常不会下降。
不知何故有些自我。其他抓取指示符+ = 1; “泄露”并且与自我不匹配。其他抓取指示符 - = 1。我想知道这次泄密怎么会发生?
答案 0 :(得分:1)
如果您想异步运行块,然后找出它们何时完成,那么相应的工具就是dispatch_group
。您可以使用dispatch_group_async()
将块分派到特定组和队列,该组将跟踪块何时完成。然后,您可以在组上同步等待以dispatch_group_wait()
结束,或者在组完成dispatch_group_notify()
时注册要调用的块。
您的解决方案无法正常工作的原因是您没有以线程安全的方式访问/改变计数器。这是导致问题的一系列微不足道的事件:
开始:self.OtherGrabbingIndicator为1
主题A :读取self.OtherGrabbingIndicator
线程B :读取self.OtherGrabbingIndicator
线程A :递增读取值并写回self.OtherGrabbingIndicator
线程B :递增读取值并写回self.OtherGrabbingIndicator
结束:self.OtherGrabbingIndicator是2
即使两个线程试图递增它,但只有一个“成功”并且你最终失去了另一个增量。这也可以在减量期间发生。如果你使用调度组,这个问题就会消失。
作为旁注,您绝不能使用dispatch_get_current_queue()
。这是一个永远不应该在实际代码中使用的调试函数。主要原因是因为您不只是在一个队列上运行,而是同时在整个队列层次上运行,但此功能只能告诉您有关一个队列的信息。此外,您可能正在某人的私人队列中运行,您当然不应该自己调度。