ΩlostA
ΩlostA

Reputation: 2601

How to execute second dispatch_async when previous first dispatch_async is finished?

I would like to add a dispatch_async sequentially but I would like them not to be launched randomly. I would like for example :

dispatch_async 1 begins...
dispatch_async 1 ends.

dispatch_async 2 begins...
dispatch_async 2 ends.

dispatch_async 3 begins...
dispatch_async 3 ends.

I need to update a sqlite, and the informations in the first dispatch are necessary for the second dispatch...

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"%@",[connection currentRequest]);

    NSLog(@"connectionDidFinishLoading");
    NSError* error;
    NSString *responseKey = [self getResponseKey:connection];

    NSDictionary* response = [NSJSONSerialization JSONObjectWithData:[receivedData objectForKey:responseKey] options:kNilOptions error:&error];
    //NSLog(@"%@", response);

    if (error)
    {
        NSLog(@"Error: %@", error);
        NSLog(@"Error: Response strange format, not an NSArray and not a NSString!\n%@", [[NSString alloc] initWithData:[receivedData objectForKey:responseKey] encoding:NSUTF8StringEncoding]);
    }

    NSLog(@"connection url : %@", connection.currentRequest.URL);

    if ([[NSString stringWithFormat:@"%@", [connection currentRequest]] rangeOfString:@"getSynchroGuest?"].location != NSNotFound) 
    {
        NSLog(@"response success");
        if ([[response valueForKey:@"lignes"] isKindOfClass:[NSArray class]])
        {
            if ([[response valueForKey:@"lignes"] count] > 0)
            {
                dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
                    //Background Thread

                [self fillDataBaseWithDict:response];

                nbTotal = nbTotal + PACKET_FOR_SYNC;

                [self WebServiceSynchroGuest:self.activityIndicator withSynchroBtn:synchroBtn withNbTotal:nbTotal];
                                 });

            }
        }
...

Thanks in advance.

SOLUTION:
                dispatch_async(serialDispatchQueue, ^{
                    [self fillDataBaseWithDict:response];
                    nbTotal = nbTotal + PACKET_FOR_SYNC;

                    dispatch_async(dispatch_get_main_queue(), ^(void){
                    [self WebServiceSynchroGuest:self.activityIndicator withSynchroBtn:synchroBtn withNbTotal:nbTotal];
                    });
                });

Upvotes: 2

Views: 611

Answers (6)

khusboo suhasini
khusboo suhasini

Reputation: 303

You can put all dispatch_async as a Serial Queue and execute one by one

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(@"block 2");
    [ NSThread sleepForTimeInterval:10.0];
    NSLog(@"Block2 End");

});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {

    // block3
    NSLog(@"block 3");
    [ NSThread sleepForTimeInterval:15.0];
    NSLog(@"Block3 End");
});
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {

    // block4
    NSLog(@"block 4");
    [ NSThread sleepForTimeInterval:20.0];
    NSLog(@"Block4 End");
});

Upvotes: 1

shiju86.v
shiju86.v

Reputation: 667

add code like this
You can set PRIORITY as well.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

});

});

Upvotes: 0

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16650

To take your Q literally, you have to nest the calls:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
^(void)
{ 
  // do some work
  …
  // finished here 

  // The next async code
  dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
  ^(void)
  { 
    // do some work
    …
    // finished here 

    // and so on

  }

}

But you should really consider to use a custom serial queue or NSOperation et al.

With a serial Q:

dispatch_queue_t stepByStepQueue = dispatch_queue_create("com.you.taks", NULL);

dispatch_async(stepByStepQueue, 
^(void)
{
  // Step
}); 

dispatch_async(stepByStepQueue, 
^(void)
{
  // By
}); 

dispatch_async(stepByStepQueue, 
^(void)
{
  // Step
}); 

Upvotes: 2

hariszaman
hariszaman

Reputation: 8424

define your own serial queue

and add code like this

 dispatch_queue_t yourSerialQueue = dispatch_queue_create("com.testcompany.testproduct.testserialqueue", DISPATCH_QUEUE_SERIAL);
 dispatch_async(yourSerialQueue, ^{ /* first task */ });
 dispatch_async(yourSerialQueue, ^{ /* second task to be executed after first task */ });

serial queue guarantees that the tasks will be exevuted in the order they are submitted and in a serial manner(one at a time)

Upvotes: 3

Ellen
Ellen

Reputation: 5190

Best approach would be to use NSOperations & add them in queue.so it would be called in sequence of completion

But if you want to do it in same way then define completion blocks & add your dispatch_async2 & dispatch_Async3 in completion blocks & call those completion blocks in end.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            // do some long running processing here

            // Check that there was not a nil handler passed.
            if( completionHandler1 )
            {
               completionHandler1();
            }
            });
        });

Upvotes: 0

mag_zbc
mag_zbc

Reputation: 6982

What you want is easily achieved with Operation instead of GCD. Operation class has addDependency(_ op: Operation) function. Put your code in BlockOperation instances, add dependencies and run them in OperationQueue

Upvotes: -1

Related Questions