iPhone - Grand Central Dispatch main thread

IosConcurrencyGrand Central-DispatchDispatch Async

Ios Problem Overview


I have been using with success, grand central dispatch in my apps, but I was wondering what is the real advantage of using something like this:

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

or even

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

I mean, in both cases you are firing a block to be executed on the main thread, exactly where the app runs and this will not help to reduce the load. In the first case you don't have any control when the block will run. I have seen cases of blocks being executed half a second after you fire them. The second case, it is similar to

[self doStuff];

right?

I wonder what do you guys think.

Ios Solutions


Solution 1 - Ios

Dispatching a block to the main queue is usually done from a background queue to signal that some background processing has finished e.g.

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

In this case, we are doing a lengthy calculation on a background queue and need to update our UI when the calculation is complete. Updating UI normally has to be done from the main queue so we 'signal' back to the main queue using a second nested dispatch_async.

There are probably other examples where you might want to dispatch back to the main queue but it is generally done in this way i.e. nested from within a block dispatched to a background queue.

  • background processing finished -> update UI
  • chunk of data processed on background queue -> signal main queue to start next chunk
  • incoming network data on background queue -> signal main queue that message has arrived
  • etc etc

As to why you might want to dispatch to the main queue from the main queue... Well, you generally wouldn't although conceivably you might do it to schedule some work to do the next time around the run loop.

Solution 2 - Ios

Dispatching blocks to the main queue from the main thread can be useful. It gives the main queue a chance to handle other blocks that have been queued so that you're not simply blocking everything else from executing.

For example you could write an essentially single threaded server that nonetheless handles many concurrent connections. As long as no individual block in the queue takes too long the server stays responsive to new requests.

If your program does nothing but spend its whole life responding to events then this can be quite natural. You just set up your event handlers to run on the main queue and then call dispatch_main(), and you may not need to worry about thread safety at all.

Solution 3 - Ios

Hopefully I'm understanding your question correctly in that you are wondering about the differences between dispatch_async and dispatch_sync?

dispatch_async

will dispatch the block to a queue asynchronously. Meaning it will send the block to the queue and not wait for it to return before continuing on the execution of the remaining code in your method.

dispatch_sync

will dispatch the block to a queue synchronously. This will prevent any more execution of remaining code in the method until the block has finished executing.

I've mostly used a dispatch_async to a background queue to get work off the main queue and take advantage of any extra cores that the device may have. Then dispatch_async to the main thread if I need to update the UI.

Good luck

Solution 4 - Ios

One place where it's useful is for UI activities, like setting a spinner before a lengthy operation:

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

will not work, because you are blocking the main thread during your lengthy thing and not letting UIKit actually start the spinner.

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

will return control to the run loop, which will schedule UI updating, starting the spinner, then will get the next thing off the dispatch queue, which is your actual processing. When your processing is done, the animation stop is called, and you return to the run loop, where the UI then gets updated with the stop.

Solution 5 - Ios

Swift 3, 4 & 5

Running code on the main thread

DispatchQueue.main.async {
    // Your code here
}

Solution 6 - Ios

Async means asynchronous and you should use that most of the time. You should never call sync on main thread cause it will lock up your UI until the task is completed. You Here is a better way to do this in Swift:

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

Its included as a standard function in my repo, check it out: https://github.com/goktugyil/EZSwiftExtensions

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDuckView Question on Stackoverflow
Solution 1 - IosRobin SummerhillView Answer on Stackoverflow
Solution 2 - Iosbames53View Answer on Stackoverflow
Solution 3 - IostimthetoolmanView Answer on Stackoverflow
Solution 4 - Iosweaselfloss1View Answer on Stackoverflow
Solution 5 - IosNiall KiddleView Answer on Stackoverflow
Solution 6 - IosEsqarrouthView Answer on Stackoverflow