【问题标题】:How should I wait for the completion of parallel async tasks in GCD?我应该如何等待 GCD 中并行异步任务的完成?
【发布时间】:2017-04-21 05:38:12
【问题描述】:

dispatch_groupdispatch_group_notify() 是在使用 GCD 的 Objective C 中等待并行异步任务完成的合理方式吗?

考虑以下几点:

dispatch_group_t requestGroup = dispatch_group_create();
dispatch_group_enter(requestGroup);
dispatch_group_enter(requestGroup);
[asyncCall1 completion:^{
    dispatch_group_leave(requestGroup);
}];

[asyncCall2 completion:^{
    dispatch_group_leave(requestGroup);
}];

dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
    // do something now that both async calls have completed
});

这是最简单、最好的方法吗?我问的原因是我有这样的代码,而且通常它似乎可以工作,尽管我很少遇到像这样的崩溃:

libdispatch.dylib`dispatch_group_leave:
0x394ea4e8:  dmb    ishst
0x394ea4ec:  ldrex  r1, [r0, #0x28]
0x394ea4f0:  adds   r1, #0x1
0x394ea4f2:  strex  r2, r1, [r0, #0x28]
0x394ea4f6:  cmp    r2, #0x0
0x394ea4f8:  bne    0x394ea4ec                ; dispatch_group_leave + 4
0x394ea4fa:  cmp.w  r1, #0xffffffff
0x394ea4fe:  ble    0x394ea50e                ; dispatch_group_leave + 38
0x394ea500:  mvn    r2, #0x80000000
0x394ea504:  cmp    r1, r2
0x394ea506:  it     eq
0x394ea508:  beq.w  0x394edd54                ; _dispatch_group_wake
0x394ea50c:  bx     lr
0x394ea50e:  trap   
0x394ea510:  mov    r8, r8
0x394ea512:  mov    r8, r8

这是被调度组捕获的未连接崩溃吗?

【问题讨论】:

  • 如果您离开群组的次数多于进入的次数,您可以获得类似的东西。在您的情况下是否有任何可能发生这种情况?我可能会建议记录每次进入和每次退出,并确保它们匹配(或维护您自己的计数器)。显然,如果它像您的代码示例一样简单,那么这不太可能是问题,但如果它比这更复杂,这是需要敏感的一件事。
  • @Rob,我认为这是不可能的,因为这些是我为该组提供的唯一入口和出口。
  • 好的,但是进入和离开组是我们许多人一直依赖的那些极其可靠的接口之一,所以我真的看不出问题中的简化代码示例如何可能生成你描述的崩溃。我怀疑问题出在其他地方(无关的请假电话,组标识符以某种方式重置等)。看起来崩溃在dispatch_group_leave,所以如果你在堆栈跟踪中上升一帧,它应该带你到调用这个函数的代码,你可以在那里查看各种属性/变量。
  • 对,我就是这么怀疑的。谢谢。

标签: objective-c grand-central-dispatch


【解决方案1】:

如果你想同步等待,你可以使用dispatch_group_asyncdispatch_group_wait

更多详情(和示例):Waiting on groups of queued tasks

而且,虽然我没用过,但我相信你也可以使用dispatch_group_notifydispatch_group_async,这样进出会更干净一点?

【讨论】:

  • 当您正在执行的任务本身是同步的时,情况确实如此。但是 OP 的示例包括对异步方法的调用,它们都有自己的完成处理程序。因此,dispatch_group_enterdispatch_group_leave 的使用正是他所需要的。在这种情况下调用dispatch_group_async 在这种情况下是不正确的。而dispatch_group_wait 更糟糕。 dispatch_group_notify 的全部目的是等待,而只是指定完成后应该调用什么。
  • 同意,如果要使用dispatch_group_async,则需要对asyncCall1asyncCall2 进行一些重构。
【解决方案2】:

@Rob 是正确的,在特定情况下,完成块可以被调用两次,这意味着对 dispatch_group_leave()dispatch_group_enter() 的调用不平衡,这是不受支持的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2016-01-15
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多