0

I'm using xcode6 with ARC.

I have a login storyboard with login stuff. I have a login process wich a wish to run in background (other thread). So cool 'im using :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Call Async URL
});

But i have some difficulties mostly because I'have to call multiple async URLs.

So no problem, I try to implement this: enter image description here

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
  dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    // Call Async URL withcallback block
    // In block
    dispatch_semaphore_signal(sema);
  });
  // Wait 30 seconds max to finish
  dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 30*10^9));

  sema = dispatch_semaphore_create(0);
  // check if is ok to continue

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    // Call Async URL withcallback block
    // In block
    dispatch_semaphore_signal(sema);
  });
  // Wait 30 seconds max to finish
  dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 30*10^9));
});

Is it ok to do this or is there an other way ?

EDIT: I have to do much more that 2 calls and it would be a mess to recursive all my asynch call.

Kwaadpepper
  • 516
  • 4
  • 15
  • 1
    You preface your question showing us a pattern where you dispatch the asynchronous request to a background queue, which is unnecessary if it's already an asynchronous API call. And in your final example where you have global dispatches nested within the master global dispatch, that's unnecessary. Just have the outer dispatch to the global queue, but lose the inner ones. But this is academic, because you shouldn't be using this semaphore pattern at all (it's inefficient use of resources to tie up thread waiting for semaphore). Ian's solution is better. – Rob Feb 18 '15 at 16:28
  • Just saying: 30*10^9 doesn't do what you think it does. – gnasher729 Feb 18 '15 at 16:34
  • Could you please explain me this ? – Kwaadpepper Feb 18 '15 at 16:40
  • 1
    The `^` operator is a bitwise XOR operator. It will operate on `300` and `9` as binary numbers: `100101100` and `1001` to return the result `100100101`, which is `293`. – Ian MacDonald Feb 18 '15 at 16:56

2 Answers2

2

I'm not sure you need to complicate things this much. You are dispatch_async to the same queue and you indicate that the calls you're making are themselves asynchronous.

Assuming that // Call Async URL withcallback block indicates the call you're making is also asynchronous and takes a callback block that it executes upon completion, all of your source code above could be replaced with the following:

[<some async call> block:^{
  [<some other async call> block:^{
  }];
}];
Ian MacDonald
  • 13,472
  • 2
  • 30
  • 51
  • i think he wants to run all call at once , without waiting for first call to complete. so it could be very much achieved with more or like same code as yours [ block:^{ }]; [ block:^{ }]; – turbo Feb 18 '15 at 16:09
  • @turbo Actually, I think OP was quite clear that he wanted a series of asynchronous requests that would _not_ run concurrently, but rather sequentially, one after the next. And Ian's answer addresses that (and is much better than the OP's code). – Rob Feb 18 '15 at 16:13
  • 1
    @Rob yes i misunderstood the diagram. – turbo Feb 18 '15 at 16:16
  • @Ian MacDonald, of course if I had just two calls to make i'll do that, but thats not the case, if fact i must do a loop of calls (at least at first synch). – Kwaadpepper Feb 18 '15 at 16:30
  • 1
    Put them all in an `NSOperationQueue`, then. – Ian MacDonald Feb 18 '15 at 16:31
  • @IanMacDonald Be careful with that, because if you do that, you have to wrap the asynchronous network request in an asynchronous `NSOperation` subclass. It's an elegant approach, but not trivial if you haven't done it before. It might be easier for the newcomer to simply have a completion block that looks up the next one in the array and calls that. – Rob Feb 18 '15 at 17:12
  • 1
    @Kwaadpepper Wait: You say you have a whole loop of these calls? Are you sure you must do these sequentially? You pay huge performance penalty doing them sequentially rather than concurrently. Do them concurrently if at all possible. – Rob Feb 18 '15 at 17:13
  • @Rob thanks, i'll use this http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues. So i'l make a NSOperation Subclass and then add dependency to run them concurently as much as possible. – Kwaadpepper Feb 19 '15 at 08:25
  • @Rob I'will also use your awesome answer here http://stackoverflow.com/questions/19373855/return-data-from-nsoperation with blocks, anyway it was a bit hard to understand, but i hope i'll make it :) – Kwaadpepper Feb 19 '15 at 09:42
  • For anyone reading, i made use of @synchronized(critical ressource) { /* code */ } as mutex to update my data hierarchy – Kwaadpepper Feb 19 '15 at 10:47
0

Late answer here but I think you want to look at DispatchGroups. DispatchGroup enter, leave, notify. This will let you wait on multiple blocks to finish and be notified on a queue when they're done.

gngrwzrd
  • 5,902
  • 4
  • 43
  • 56