Search code examples
iosobjective-cgrand-central-dispatch

dispatch_group_async within dispatch_group_notify


I would like to execute some sequential jobs in a iOS application. I want to ensure that a job is not executed until the previous one has finished. Firstly I tried to do something like this:

group = dispatch_group_create();
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_async(group, queue, ^{
// Job 1
// ...
});
dispatch_group_async(group, queue, ^{
// Job 2
// ...
});

On this way, sometimes the job 2 starts executing when the job 1 is still executing.

Then I thought of using this way:

group = dispatch_group_create();
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_notify(group, queue, ^{
// Job 1
// ...
});
dispatch_group_notify(group, queue, ^{
// Job 2
// ...
});

The behavior is the same, because the job 1 hasn't been asynchronously dispatched, so the dispatch_group_notify() function thinks there's nothing executing and the job 2 is dispatched without waiting to the job 1.

I found another solution:

group = dispatch_group_create();
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
dispatch_group_notify(group, queue, ^{
    dispatch_group_async(group, queue, ^{
    // Job 1
    // ...
    });
});
dispatch_group_notify(group, queue, ^{
    dispatch_group_async(group, queue, ^{
    // Job 2
    // ...
    });
});

Now everything works fine.

Do you find any problem with this dispatch-inside-dispatch structure? Or is it fine?


Solution

  • The global queue that you get with

    queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    

    is a concurrent queue. If you want your jobs to execute sequentially, just create a serial queue with

    queue = dispatch_queue_create("com.company.myqueue", NULL);