AppsDev
AppsDev

Reputation: 12499

Grand Central Dispatch and concurrent tasks

I need to perform three tasks that are independent one from each other, so I'd like to execute them concurrently. But I need them all to have finished to notify another object. AFAIK, *dispatch_apply* creates concurrent threads, but it iterates a collection or an array of objects and performs the same task a number of loops, and I want to perform a different task for each thread. Is it possible to do what I want by using GCD? If not, what should be the best way?

Thanks!

Upvotes: 3

Views: 1495

Answers (3)

Rob
Rob

Reputation: 437422

I know you asked about GCD, but NSOperationQueue is another possibility. For example:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 3;

// create my completion operation (which will be added to the queue later, once
// the dependencies with all of the other operations has been established)

NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"All done");
}];

// let's add our three operations

NSBlockOperation *operation;

operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"starting task 1");
    sleep(5);
    NSLog(@"stopping task 1");
}];

[completionOperation addDependency:operation];
[queue addOperation:operation];

operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"starting task 2");
    sleep(4);
    NSLog(@"stopping task 2");
}];

[completionOperation addDependency:operation];
[queue addOperation:operation];

operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"starting task 3");
    sleep(6);
    NSLog(@"stopping task 3");
}];

[completionOperation addDependency:operation];
[queue addOperation:operation];

// now let's add the completion operation (which has been configured as dependent
// upon the other operations

[queue addOperation:completionOperation];

There are tons of different ways of tackling this problem, but NSOperationQueue is another option. The Concurrency Programming Guide discusses all of the options.

Upvotes: 4

David Hoerl
David Hoerl

Reputation: 41632

Dispatch Groups are what you need. Look at the GCD functions. What you will do is create the group and a concurrent queue (or use thee standard ones). Associate the three operations (blocks) with the dispatch_group, then create a forth block, and have that block do a dispatch_group_wait (typing names by memory), then when that returns, it can post a 'success' message to some other object. Put the block with the wait into any concurrent queue.

I do exactly this in my app.

Upvotes: 4

Kurt Revis
Kurt Revis

Reputation: 27984

Use a dispatch_group. The Concurrency Programming Guide gives one example, and there is more API that might also help you.

  • Create a dispatch group using dispatch_group_create.

  • Put each "task" in the group by enqueuing it using dispatch_group_async.

    (Or, manually tell GCD when each task starts and stops, using dispatch_group_enter and dispatch_group_leave.)

  • To run a block when all tasks in the group have completed, enqueue it using dispatch_group_notify.

    (Or, in the unlikely case that the design of your app allows you to wait synchronously, use dispatch_group_wait instead.)

  • When you're done with the group, dispatch_release it.

Upvotes: 6

Related Questions