1

I am creating a serial queue in which i add two task as shown below

dispatch_queue_t serial = dispatch_queue_create("com.apple.serial", DISPATCH_QUEUE_SERIAL);

**//Task 1**
dispatch_async(serial, ^{

    [NMUserAPIManager getUserProfileData:^(NMUser *objUser) {

        NSLog(@"Get User Profile .....");

        _objUser = objUser;

    }];

});


**//Task 2**
dispatch_async(serial, ^{

    [NMUserAPIManager getUserRecentTransactionData:^(NSDictionary *responseDictionary) {
        _accountTableView.hidden = NO;
        [self recentTransactionSetup:responseDictionary];

        NSLog(@"Get User Recent transaction");

        dispatch_async(dispatch_get_main_queue(), ^{
            [self reloadTableData];
        });
    }];

});

Inside that two task i am calling web service with NSURLSession. Problem is that before my Task 1 completion handle Task2 completion handle get called. According to theory by using serial queue each task waits for the previous task to finish before being executed. It my understanding is correct.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • The things that are serialized by your queue are the calls to the `NMUserAPIManager` methods. That means `getUserRecentTransactionData` would be called after `getUserProfileData` is called. It doesn't make any guarantees about the order of the completion handlers. – Phillip Mills May 25 '17 at 20:10
  • You are adding the issuance of your requests in the serial queue, but not their respective responses. The easiest solution is to get rid of GCD and just issue the second request from the completion handler of the first request. If you really want to use a serial queue to keep track of these requests, you could wrap the individual requests in a custom `NSOperation` subclass (see https://stackoverflow.com/a/23837970/1271826 or https://stackoverflow.com/a/24943851/1271826). If you're doing just two requests, that might be overkill. – Rob May 25 '17 at 20:26

1 Answers1

1

NSURLSession's already run on a background thread, so the issue you are seeing here is that as far as your serial queue is concerned once you call 'getUserProfileData:' technically the work for that block in your queue is finished because the NSURLSession is running on a different thread. If your main goal here is to simply call your second task after your first one completes I don't think you need your own queue you would probably be better off simply doing something like:

[NMUserAPIManager getUserProfileData:^(NMUser *objUser) {

    NSLog(@"Get User Profile .....");

    _objUser = objUser;

   [self getUserTransactions];

}];

-(void)getUserTransactions
{
       [NMUserAPIManager getUserRecentTransactionData:^(NSDictionary *responseDictionary) {
        _accountTableView.hidden = NO;
        [self recentTransactionSetup:responseDictionary];

        NSLog(@"Get User Recent transaction");

        dispatch_async(dispatch_get_main_queue(), ^{
            [self reloadTableData];
        });
    }];
 }

EDIT:

If you are looking for something a little more robust I would check out this post for how you can subclass NSOperation to make your own Asynchronous Operation which you can then use with an NSOperationQueue.

zfetters
  • 447
  • 2
  • 11