performBlockAndWait another answer, try to explain why performBlockAndWait will always execute in the calling thread.
performBlock completely asynchronous. It always queues the queue for the receiving MOC, and then returns immediately. In this way,
[moc performBlock:^{ // Foo }]; [moc performBlock:^{
will place two blocks in the queue for moc. They will execute asynchronously. Some unknown thread will pull the blocks out of the queue and execute them. In addition, these blocks are wrapped in their own autocomplete pool, and they will also represent the entire Core Data user event ( processPendingChanges ).
performBlockAndWait does NOT use an internal queue. This is a synchronous operation performed in the context of the calling thread. Of course, he will wait until the current operations in the queue are completed, and then this block will be executed in the calling thread. This is documented (and confirmed in several WWDC presentations).
In addition, performBockAndWait is repeated, so nested calls occur in this calling thread.
Core Data engineers were very clear that the actual thread in which the queue-based MOC operation is performed does not matter. This is synchronization using the performBlock* API key.
So, consider "executeBlock" as "This block is placed in a queue that must be executed at some indefinite time, in some indefinite thread. The function will return to the caller as soon as it is queued"
performBlockAndWait : "This block will be executed for some indefinite time in the same thread. The function will return after this code has been completely executed (what will happen after the current queue associated with this MOC is discharged)."
EDIT
Are you sure that "executeBlockAndWait DOES NOT use an internal queue"? I think so. The only difference is that performBlockAndWait will wait for the block to complete. And what do you mean by calling a thread? In my opinion, [moc performBlockAndWait] and [moc performBloc] run in their private queue (main or main). An important concept here is the moc to which the queue belongs, and not vice versa around. Please correct me if I am wrong. - Philip007
Unfortunately, I formulated the answer the way I did, because, taken on my own, this is not true. However, in the context of the original question, this is correct. In particular, when calling performBlockAndWait in a private queue, the block will be executed in the thread that calls the function β it will not be queued and executed in the "private thread".
Now, before I even delve into the details, I want to emphasize that depending on the internal work of libraries it is very dangerous. All you really need is that you can never expect a particular thread to execute a block, with the exception of everything related to the main thread. Thus, expecting that performBlockAndWait will not execute on the main thread, it is not recommended because it will execute on the thread that called it.
performBlockAndWait uses GCD, but also has its own layer (for example, to prevent deadlocks). If you look at the GCD code (which is open source), you can see how synchronized calls work - and in general, they synchronize with the queue and call the block in the thread that calls this function - if the queue is not the main queue or global queue. In addition, during WWDC negotiations, Core Data engineers emphasize that performBlockAndWait will work in the calling thread.
So, when I say that it does not use an internal queue, this does not mean that it does not use data structures at all. It should synchronize the call with the blocks already in the queue, and those that are represented in other threads and other asynchronous calls. However, when calling performBlockAndWait it does not queue the block ... instead, it synchronizes access and launches the presented block in the thread that calls the function.
Now SO is not a good forum for this because it is a bit more complicated than that, especially wrt in the main queue and global GCD queues - but the latter is not important for Core Data.
The main thing is that when you call any function performBlock* or GCD, you should not expect that it will work in any particular thread (except that it is connected to the main thread), because the queues are not threads, but only the main queue will be run blocks on a specific thread.
When the main data is called, performBlockAndWait block will be executed in the calling thread (but will be synchronized accordingly with everything sent to the queue).
I hope this makes sense, although it probably just caused more confusion.
EDIT
In addition, you can see the unspoken consequences of this, because the way that performBlockAndWait provides re-entry support upsets the FIFO blocks. As an example...
[context performBlockAndWait:^{ NSLog(@"One"); [context performBlock:^{ NSLog(@"Two"); }]; [context performBlockAndWait:^{ NSLog(@"Three"); }]; }];
Please note that strict adherence to the FIFO queue guarantee will mean that the nested performBlockAndWait (βThreeβ) will execute after the asynchronous block (βTwoβ), since it was sent after the asynchronous block was sent. However, this is not the case as it would be impossible ... for the same reason, a deadlock occurs with nested dispatch_sync calls. You just need to know something if you are using the synchronous version.
In general, avoid synchronous versions whenever possible, because dispatch_sync can cause a deadlock, and any re-version, such as performBlockAndWait , will have to make some kind of βbadβ decision to support it ... for example, have synchronization versions βjumpβ in queue.