Search code examples
iosgrand-central-dispatchnsoperationnsoperationqueue

Asynchronous url requests inside dispatch_async


I am trying to implement asynchronous url requests in a particular function, I want all these requests to complete and then do a particular action but the action precedes the requests i.e, it is getting called before the requests complete.

dispatch_queue_t fetchQ = dispatch_queue_create("Featured Doc Downloader", NULL);
        dispatch_async(fetchQ, ^{
            [self myAsyncMultipleURLRequestFunction];
            dispatch_sync(dispatch_get_main_queue(), ^{
                [self updateUIFunction];
            });
        });

-(void)myAsyncMultipleURLRequestFunction
   {
    for (int i=0; i<count; i++) 
     {
     NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];          
     }
   }

now updateUIFunction gets called before myAsyncMultipleURLRequestFunction completes all requests. Also tried this with NSOperaitonQueue but could not do what I really want.

[_operationQ addOperationWithBlock: ^ {
     for (int i=0; i<count; i++)
      {
     NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];          
      }
    }

[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
         // updating UI
         [self updateUIFunction];
    }];
}];

I know this is simple but I am running outta time, any help is appreciated.


Solution

  • @tkanzakic is on the right path. The correct construct to use is the dispatch_group_t. But the implementation could be improved. By using a semaphore you can launch all your downloads asynchronously and still make sure that you don't have too many running concurrently. Here is a code sample that illustrates how you should use dispatch_group_t as well as make all your downloads parallel:

    dispatch_queue_t fetchQ = dispatch_queue_create("Featured Doc Downloader", NULL);
    dispatch_group_t fetchGroup = dispatch_group_create();
    
    // This will allow up to 8 parallel downloads.
    dispatch_semaphore_t downloadSema = dispatch_semaphore_create(8);
    
    // We start ALL our downloads in parallel throttled by the above semaphore.
    for (int i=0; i<count; i++) {
        dispatch_group_async(fetchGroup, fetchQ, ^(void) {
            dispatch_semaphore_wait(downloadSema, DISPATCH_TIME_FOREVER);
            NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:requestArray[i] delegate:self];
            dispatch_semaphore_signal(downloadSema);
        });
    }
    
    // Now we wait until ALL our dispatch_group_async are finished.
    dispatch_group_wait(fetchGroup, DISPATCH_TIME_FOREVER);
    
    // Update your UI
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self updateUIFunction];
    });
    
    // Release resources
    dispatch_release(fetchGroup);
    dispatch_release(downloadSema);
    dispatch_release(fetchQ);