iPhone - Grand Central Dispatch main thread

145,350

Solution 1

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

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

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

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

Swift 3, 4 & 5

Running code on the main thread

DispatchQueue.main.async {
    // Your code here
}
Share:
145,350
Duck
Author by

Duck

Updated on April 13, 2020

Comments

  • Duck
    Duck about 4 years

    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.

    • Brooks Hanes
      Brooks Hanes over 10 years
      By the way, throwing a main queue into a dispatch_sync will result in a deadlock.
    • Brooks Hanes
      Brooks Hanes over 10 years
      Just read it in docs: "Unlike dispatch_async, [dispatch_sync] does not return until the block has finished. Calling this function and targeting the current queue results in deadlock."... But perhaps I'm reading this wrong... (the current queue does not mean main thread). Please correct if I am wrong.
    • mfaani
      mfaani over 7 years
      @BrooksHanes not always true. It will result a deadlock if you are already on the main thread. If not then there wouldn't be a deadlock. See here
  • Duck
    Duck over 12 years
    thanks, but I am asking about the advantages from sending something to the main queue, being on the main queue.
  • Duck
    Duck over 12 years
    Ah, I see. So, I am right. There's no advantage in doing that if you are already on the main queue, just if you are on another queue and want to update the UI. Thanks.
  • Robin Summerhill
    Robin Summerhill over 12 years
    Just edited my answer to talk about why it's not very useful to do this from the main queue.
  • joerick
    joerick over 12 years
    Also, I think there's a bug in iOS 4 (might have gone in iOS 5), where dispatch_sync to the main queue from the main thread just causes a hang, so I would avoid doing that entirely.
  • Robin Summerhill
    Robin Summerhill over 12 years
    That's not a bug, that's the expected behaviour. Not very useful behaviour admittedly but you always need to be aware of deadlocks when using dispatch_sync. You can't expect the system to protect you from programmer error all the time.
  • Nilesh Tupe
    Nilesh Tupe over 11 years
    What is backgroundQueue here? How do I create backgroundQueue object
  • swiftBoy
    swiftBoy about 11 years
    @NileshTupe just check the updated answer please!, btw already Robin has described it in great way! +1 for this.
  • Dan Rosenstark
    Dan Rosenstark over 8 years
    @Jerceratops yes but it allows the current runloop to complete.
  • Jerceratops
    Jerceratops over 8 years
    Yes, but it's still terrible. It still blocks the UI. I might press another button right after this one. Or try and scroll. "(do something lengthy)" should not happen on the main thread, and dispatch_async to let the button click "finish" is not an acceptable solution.
  • MikeG
    MikeG over 8 years
    i dont understand something here.. so the first call to the background queue initiates this lengthy calculation. But since it is called asynchronously, doesn't that mean that the nested call to dispatch on main queue could begin before the calculation is complete?
  • mfaani
    mfaani over 7 years
    In your answer, where have discussed what is dispatch_sync(dispatch_get_main_queue() and where it should or shouldn't be used? You only wrote about the async kind...