6

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.

3 Answers 3

10

@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);
Sign up to request clarification or add additional context in comments.

1 Comment

I will try this, looks promising.
3

You can create a dispatch_group_t and then use dispatch_group_notify to execute the updateUIFunction when the previous block of the group finish running, for example:

dispatch_queue_t fetchQ = dispatch_queue_create("Featured Doc Downloader", NULL);
dispatch_async(fetchQ, ^{
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        [self myAsyncMultipleURLRequestFunction];
    });
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateUIFunction];
        });
    });
});

10 Comments

Thanks will try this and let you know!
Hey @tkanzakic it is not working, same as before. updateUIFUnction gets called before myAsyncMultipleURLRequestFunction gets completed.
I have made a small modification of the dispatch_group_notify block, I remember that I need to implement it this way is some project, give it a try
by the way, are your connections running asynchronously?
Yes all connections are asynchronous.
|
1

First Configure run loop.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    [NSURLConnection connectionWithRequest:request delegate:self];
    while(!self.finished) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
});

Try this

1 Comment

what do you mean by self.finished here?? Is it a BOOL??

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.