dispatch_sync always scheduling a block on Main Thread
Solution 1
dispatch_sync() dispatches the block on the same thread, that's normal.
EDIT
Apple's Documentation does not only says this, also says this:
As an optimization, this function invokes the block on the current thread when possible.
As a side note (I know you're talking about the synchronous version, but let's precisate this) I would say that also dispatch_async() may cause multiple blocks to be executed in the same thread.
Solution 2
For a background block, use
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// background code
});
Note it's _async and not _sync
EDIT: Likewise, to execute something on main thread, use
dispatch_async(dispatch_get_main_queue(), ^{
// main thread code
});
Solution 3
It is important to realize that Grand Central Dispatch can guarantee that a block submitted to the main queue will run on the main thread, but a block submitted to any other queue has no guarantees about what thread a block will execute on.
No guarantee is made regarding which thread a block will be invoked on; however, it is guaranteed that only one block submitted to the FIFO dispatch queue will be invoked at a time.
Grand Central Dispatch manages a pool of threads and reuses existing threads as much as possible. If the main thread is available for work (i.e. idle) a block can be executed on that thread.
Comments
-
Evol Gate almost 2 years
I am executing a block using dispatch_sync and the block is executed correctly. But this block is executed on the main thread. As per the Apple Doc:
Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue.
which means (or what I understood) that current process that is being executed will run on a separate thread.
Below is the code that I am using to judge what's going on. It is being called inside NSURLConnection's didReceiveData: delegate method (I know I should not do that inside the didReceiveData: delegate method - but this is just a sample to focus on dispatch_sync). Following are the different ways that I can assume as a proof of my conclusion:
Using dispatch_sync on a Global Concurrent Queue
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if ([NSThread isMainThread]) { NSLog(@"Main Thread"); } else NSLog(@"Not on Main Thread"); //Some Process });
Output -
Main Thread Main Thread Main Thread // Main Thread printed till didReceiveData: gets called
Using dispatch_sync on a self created queue using dispatch_queue_create
// Create queue somewhere else like this dispatch_queue_t newQueue = dispatch_queue_create("WriteQueue", DISPATCH_QUEUE_SERIAL); dispatch_sync(newQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"Main Thread"); } else NSLog(@"Not on Main Thread"); //Some Process });
Output -
Main Thread Main Thread Main Thread // Main Thread printed till didReceiveData: gets called
I am a bit surprised here, block is executed always on the main thread or am I missing something. Because it seems to be going against the Apple Doc I think so. Does anyone know what this is all about?
Update: As per other discussions I understand that dispatch_sync executes a block on the same thread (most of the times), then why apple docs' statements are contradicting in some ways. Why apple says "The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue." Or am I still missing something?
-
Evol Gate over 11 yearsI already mentioned it is just to focus on dispatch_sync. I know i can do it using dispatch_async(dispatch_get_main_queue()
-
Evol Gate over 11 yearsYeah I already know that, but it contradicts with the apple doc
-
Joshua Nozzi over 11 yearsI don't see it as a contradiction but more an affirmation (your bolded part) that it's not up to you to choose the target thread for the used queue nor is it guaranteed to be consistent. Still, file a bug against the docs and ask for clarification on this point.
-
Evol Gate over 11 years@JoshuaNozzi I think you're correct. I need to file a bug and ask for clarification
-
Evol Gate over 11 years@RamyAlZuhouri The point that you quoted above - Is it also written in docs for iOS, because I only saw it in Mac development docs.
-
Ramy Al Zuhouri over 11 years@Evol Gate it's written in both documentations: iOS and OS X.
-
Victor Engel almost 11 years@Ismael, what if dispatch_async(dispatch_get_main_queue(), ...) is called from the main queue. According to the doc, if I'm reading it right, that would cause a deadlock.
-
Ismael almost 11 yearsNo, it will not cause a deadlock. Most likely it will be added to the main thread queue and be processed after the thread is freed
-
Nisar Ahmad about 6 years@quelish your answer make sense . . . would you like to share the reference of your comments I mean any Apple Doc link ? Thanks
-
quellish about 6 years@NisarAhmad, it is in the headers: opensource.apple.com/source/libdispatch/libdispatch-913.30.4/… as well as
man dispatch_queue_create
-
XLE_22 about 6 years@quelish : if the MainThread may be used in another queue than the MainQueue, does it mean that the associated current loop at that time is the MainRunLoop ? (I understood a loop is associated with a thread)