Dispatch group and NSNotification

799 views Asked by At

My issue is simple. I have 3 tasks, one is triggered by an NSNotification. How to I wait for all task to be completed before proceeding.

So far, I tried using dispatch group but can't find a way to add the task triggered by NSNotification. (I tried adding the dispatch command within the method triggered by the NSNotification, but if the notification comes after task 1 and 2, it's too late to add to the group as it is already completed.)

_asyncDispatch = dispatch_group_create();


dispatch_group_async(_asyncDispatch,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    [self doTask1];
});

dispatch_group_async(_asyncDispatch,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    [self doTask2];
});

dispatch_group_notify(_asyncDispatch,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {

    // We're done!
});
2

There are 2 answers

0
GrandSteph On BEST ANSWER

Thanks @Sega-Zero for your guidance. Here is the solution I implemented.

_operationQueue = [[NSOperationQueue alloc] init];
_semaphore = dispatch_semaphore_create(0);

NSOperation *uploadOperation = [NSBlockOperation blockOperationWithBlock:^{
    [self doFirstTask];
}];

NSOperation *downloadOperation = [NSBlockOperation blockOperationWithBlock:^{
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
}];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    [self doNextMethod];
}];

[completionOperation addDependency:uploadOperation];
[completionOperation addDependency:downloadOperation];

[_operationQueue addOperations:@[uploadOperation, downloadOperation, completionOperation] waitUntilFinished:NO];

And then, in the method triggered by the NSNotification

-(void)methodTriggeredByNotif:(NSNotification *)notification {

// doing some serious stuff here and when done
dispatch_semaphore_signal(_semaphore);}

Voila. Thanks to all.

7
Sega-Zero On

I suggest you to use NSOperation and NSOperationQueue instead. You can link all operations as a dependency to each other and wait until all three will be done. Then in the last operation's completion block do your done handler.

If you're confused with it, you can still use dispatch group, but in slightly another way. Use dispatch_group_enter/dispatch_group_leave + dispatch_group_wait. Something like that:

dispatch_group_t waitGroup = dispatch_group_create();
dispatch_group_enter(waitGroup);
dispatch_async(otherQueue, ^{
    //long-running code
    dispatch_group_leave(waitGroup);
}
dispatch_group_wait(waitGroup, DISPATCH_TIME_FOREVER);

call dispatch_group_enter when one of your task begins running and dispatch_group_leave after task has been completed. Call dispatch_group_wait in the place where you need to wait until all tasks will be completed. Do not wait in the main thread! It is better to create a separate queue for this.

But i encourage you to use NSOperations. It's pretty much more controllable and able to cancel.