Thursday, 25 September 2014

Call two or more async services using Dispatch Group

// https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

// for details see chapter of Apple's iOS Developer Library's Concurrency Programming Guide


//create dispatch group
dispatch_group_t  group = dispatch_group_create();

dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block1
    NSLog(@"Block1");
    [NSThread sleepForTimeInterval:5.0];
    NSLog(@"Block1 End");
});


dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block2
    NSLog(@"Block2");
    [NSThread sleepForTimeInterval:8.0];
    NSLog(@"Block2 End");
});

dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block3
    NSLog(@"Block3");
});


dispatch_release(group);

and could produce output like this:
2012-08-11 16:10:18.049 Dispatch[11858:1e03] Block1
2012-08-11 16:10:18.052 Dispatch[11858:1d03] Block2
2012-08-11 16:10:23.051 Dispatch[11858:1e03] Block1 End
2012-08-11 16:10:26.053 Dispatch[11858:1d03] Block2 End
2012-08-11 16:10:26.054 Dispatch[11858:1d03] Block3









If you do not have control over the dispatch_async calls for your blocks, as might be the case for async completion blocks, you can use the GCD groups using dispatch_group_enter and dispatch_group_leave directly.


// create a group
dispatch_group_t group = dispatch_group_create();

// pair a dispatch_group_enter for each dispatch_group_leave
dispatch_group_enter(group);       // pair 1 enter
[self computeInBackground:1 completion:^{
    NSLog(@"1 done");
    dispatch_group_leave(group);      // pair 1 leave
}];

// again... (and again...)
dispatch_group_enter(group);          // pair 2 enter
[self computeInBackground:2 completion:^{
    NSLog(@"2 done");
    dispatch_group_leave(group);         // pair 2 leave
}];

// dispatch your final block after all the dispatch_group_enters
dispatch_async(dispatch_get_main_queue(), ^{
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"finally!");
});



In this example, computeInBackground:completion: is implemented as:
- (void)computeInBackground:(int)no completion:(void (^)(void))block {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"%d starting", no);
        sleep(no*2);
        block();
    });
}



Output (with timestamps from a run):
12:57:02.574  2 running
12:57:02.574  1 running
12:57:04.590  1 done
12:57:06.590  2 done
12:57:06.591  finally!


No comments:

Post a Comment