2

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];
                    });
                });
4
  • You can put dispatch_async 2 inside the completion block of dispatch_async 1 and so on... Commented Jul 13, 2017 at 9:24
  • I cannot because this is in connectionDidFinishLoading, I have to launch the WS and wait for the answer before to launch the dispatch Commented Jul 13, 2017 at 9:28
  • You can, if there is a completion handler. Simply put it in the last line of the handler. Commented Jul 13, 2017 at 9:28
  • stackoverflow.com/a/37806522/2000162 Commented Jul 13, 2017 at 10:08

6 Answers 6

3

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)

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect, it works. And for info, if a request is needed in the disptach, it has to be done on the main thread. I updated my ticket.
2

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
}); 

Comments

1

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");
});

1 Comment

This is a low-quality answer. If you are sure of your answer, please edit it by giving more details, sample code or pseudo-code.
0

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();
            }
            });
        });

Comments

0

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), ^{

});

});

Comments

-1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.