JPC
JPC

Reputation: 8296

Using GCD to wait for a condition

I'm trying to enforce a specific order for tasks to complete using Grand Central Dispatch but I'm having a bit of trouble understanding the correct way to do it. I tried using groups in the following way:

Initialization:

startup = dispatch_group_create();

Tasks that need to wait:

//Don't want to wait on the main thread, so dispatch async to a concurrent queue
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0L),^{
        //Wait until we're finished starting up
        dispatch_group_wait(startup,DISPATCH_TIME_FOREVER);
        //Now we can do this stuff back on the main queue
        dispatch_async(dispatch_get_main_queue(),^{
            //Do work
        });
    });

Work that I need to wait for:

dispatch_group_async(startup,dispatch_get_main_queue(),^{ // work });

Due to the nature of my app, the tasks that need to wait can occur BEFORE the work that I need to wait for. What I really want is the ability to wait on a condition that way when the condition is done, it's done, and all future threads can do their thing. Does GCD have this?

Upvotes: 1

Views: 3620

Answers (2)

timthetoolman
timthetoolman

Reputation: 4623

I'm not sure of all the details of your implementation, so forgive me if I'm repeating what you already know.

  1. Create a dispatch group
  2. Use dispatch_group_async to a serial queue. Using the serial queue, you are assured that your tasks are processed in the order you wish. Use a concurrent queue if you the order doesn't matter, but your question said that they had to complete in a specific order.
  3. After you are done dispatching all of your tasks, use dispatch_group_notify. This will execute a block on the queue you specify once all the tasks assigned to the group have finished processing.

    dispatch_group_notify(startup, dispatch_get_main_queue(), ^{
          // Don't forget to release the dispatch group!
          dispatch_release(startup)
         // perform work block;
    });
    

For a particular parsing activity, I need to do some processing of data that can be done while the rest of the parsing activity is ongoing. I assign the processing to a group on a concurrent queue. Then when my parsing is done, I check to see if the group is done. If it is done, I clean things up. If not, utilize the dispatch_group_notify() and execute the work afterwards. Something along these lines:

double delayInSeconds = 2.0;
dispatch_time_t groupWaitTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
if (dispatch_group_wait(myDispatchGroup, groupWaitTime)==0){
    NSLog(@"dispatch group completed in time");
    dispatch_release(myDispatchGroup);
    [self parsingCompleteWithActivity:activity];
}else{
    NSLog(@"dispatch group did not complete in time");
    dispatch_group_notify(myDispatchGroup, dispatch_get_main_queue(), ^{
            dispatch_release(myDispatchGroup);
            [self parsingCompleteWithActivity:activity];
    });
}

Good luck!

Upvotes: 2

JPC
JPC

Reputation: 8296

Works if I use a semaphore and then signal after each call to wait. Also works if I call dispatch_group_enter and dispatch_group_leave.

Upvotes: 0

Related Questions