在Swift中,dispatch_group_leave崩溃问题

18

这种情况很少发生。以下是堆栈跟踪的最后一行:

0  libdispatch.dylib              0x0000000197a85a9c dispatch_group_leave + 48

使用 dispatch_group_leave 的方式是在一个完成闭包中调用它,就像这样:

  dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                { () -> Void in
                    let query = HKStatisticsCollectionQuery(quantityType: quantityType,
                        quantitySamplePredicate: nil,
                        options: statisticOptions,
                        anchorDate: anchorDate,
                        intervalComponents: interval)
                    query.initialResultsHandler = {

                        complete()

因此,我们将其分派到后台线程,运行HKStatisticsCollectionQuery,然后调用名为complete的函数参数闭包。在complete内部调用dispatch_group_leave并导致崩溃。

非常感谢任何想法! 谢谢!


https://dev59.com/5mAf5IYBdhLWcg3wukpk#43548031 - pkamb
2个回答

28
如果dispatch_group_leave调用没有与dispatch_group_enter平衡,则可能会发生崩溃。

有趣。在第一个闭合之前我有一个回车被调用了。嗯。 - jestro
1
我想这就是原因。某些分支被调用得太快了。将所有的进入和通知操作移到可调用分支之前。谢谢! - jestro
5
@mustafa 有没有办法防止调用 dispatch_group_leave 次数超过应该的情况?也就是说,对于我无法确定完成块(其中调用 dispatch_group_leave)不会被调用多次的情况,有什么方法可以解决呢? - ofer2980
@ofer2980 你找到方法了吗? - hyouuu
我们可以在 dispatch_group_leave 后添加一点睡眠线程调用。这将有助于 dispatch_group 应用并发规则。它救了我的一天。 - Mohd Haider

8

在最坏的情况下,您可以通过查看折扣组的debugDescription字符串来检查其count数量:

let count = self.groupExecuting.debugDescription.components(separatedBy: ",").filter({$0.contains("count")}).first!.components(separatedBy: CharacterSet.decimalDigits.inverted).filter({Int($0) != nil})
assert(count.first != "0")

这种策略在这个问题中进一步探讨:DispatchGroup:检查有多少人“进入”


19
什么鬼东西 - Munib
2
@PranoyC 这显然不应该用于生产代码,但在调试过程中非常有帮助。 - Hannes Hertach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接