From Grand Central Dispatch (GCD) Reference: dispatch_async
The target queue determines whether the block is invoked serially or concurrently with respect to other blocks submitted to that same queue.
From OperationQueues: Performing Tasks on the Main Thread
You can get the dispatch queue for your application’s main thread by calling the dispatch_get_main_queue function. Tasks added to this queue are performed serially on the main thread itself. Therefore, you can use this queue as a synchronization point for work being done in other parts of your application.
From these two pieces of information, we know the main queue is a serial dispatch queue and dispatch_async()
will follow the rules of serial execution.
So the simple answer is the task will be run on the main queue sometime after the completion of the current context.
I couldn't find a official description of the run loop's internals, but rob mayoff a good breakdown.
Order of operations in runloop on iOS
Note that the run loop is structured so only one of these branches happens on each iteration:
- Ready timers fire, or
- Blocks on dispatch_get_main_queue() run, or
- A single version 1 source is dispatched to its callback.
If the context is an input source or a timer fire, then the task will happen in a different iteration of the run loop. If the context is a dispatched task, then the task may actually run within the same iteration of the run loop.