1

Is a dispatch_group and dispatch_group_notify() a reasonable way to wait for parallel async tasks to complete in Objective C with GCD?

Consider the following:

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
});

Is this the simplest, best way? The reason I ask is that I have code just like this and generally it seems to work, though very rarely I have crashes like:

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

Is this an unconnected crash that's getting caught by the dispatch group?

4
  • 1
    You can get something similar if you leave the group more times than you entered. Is there any possibility of that happening in your situation? I might suggest logging every enter and every exit, and make sure they match up (or maintain your own counter). Clearly if its as simple as your code sample here, that's unlikely to be the issue, but if it's more complicated than that, this is one thing to be sensitive to. Commented Apr 7, 2015 at 22:47
  • @Rob, I would think that's impossible, since those are the only entrances and exits I have for that group. Commented Apr 8, 2015 at 18:41
  • OK, but entering and leaving groups is one of those extremely solid interfaces that many of us rely upon all the time, so I really do not see how the simplified code sample in the question would possibly generate the crash you describe. I suspect the problem rests elsewhere (extraneous leave calls, group identifier was reset somehow, etc.). It looks like the crash is in dispatch_group_leave, so if you go up one frame in the stack trace, it should take you to your code that called this function and you can look at the various properties/variables there. Commented Apr 8, 2015 at 18:54
  • 1
    Right, that's what I suspected. Thanks. Commented Apr 8, 2015 at 19:25

2 Answers 2

1

If you want to wait synchronously, you can utilize dispatch_group_async and dispatch_group_wait.

More details (and an example): Waiting on groups of queued tasks

And, although I haven't used it, I'm sure you could leverage dispatch_group_notify with dispatch_group_async as well, which might be a little cleaner then entering and leaving?

Sign up to request clarification or add additional context in comments.

2 Comments

That's true when the tasks you are performing are, themselves, synchronous. But the OP's example consists of calls to methods that are asynchronous, both with their own completion handlers. Thus, the use of dispatch_group_enter and dispatch_group_leave is precisely what he needs. Calling dispatch_group_async in this situation would be incorrect in this scenario. And dispatch_group_wait is even worse. The entire purpose of dispatch_group_notify is to not wait, but rather to just specify what should be called when they're done.
Agreed, if dispatch_group_async were to be used, some refactoring of asyncCall1 and asyncCall2 would be required.
1

@Rob was correct and there was a specific case where a completion block could be called twice, meaning that the the calls to dispatch_group_leave() and dispatch_group_enter() were unbalanced, which is unsupported.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.