Showing posts with label Dispatch Group. Show all posts
Showing posts with label Dispatch Group. Show all posts

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!