NSManagedObjectContext's performBlockAndWait: not executing on the receiver's queue

核能气质少年 提交于 2019-12-23 13:34:05

问题


I've noticed that it's possible for an NSManagedObjectContext with an NSMainQueueConcurrencyType to performBlockAndWait: and execute the block on a queue other than the receiver's (main) queue.

For example, the following code results in my parentContext executing the block on the childContext's queue if my parentContext is of type NSMainQueueConcurrencyType and my childContext is of type NSPrivateQueueConcurrencyType:

[childContext performBlockAndWait:^{
    //Thread 1, Queue: NSManagedObjectContext Queue
    [parentContext performBlockAndWait:^{
        //Thread 1, Queue: NSManagedObjectContext Queue
        //This is the same queue as the child context's queue
    }];
}];

In contrast, the following code works as expected – my parentContext executes the block on the main queue:

[childContext performBlock:^{
    [parentContext performBlockAndWait:^{
        //Thread 1, Queue: com.apple.main-thread
    }];
}];

Is this the expected behavior? It is certainly confusing me since the docs state "performBlockAndWait: synchronously performs a given block on the receiver’s queue."


回答1:


You should not be worried on what thread blocks are executed. What the performBlock: and performBlockAndWait: methods guarantee is thread safety. Thus, calling performBlockAndWait: from the main thread does not mean there would be a context switch to a background thread - it is very expensive and it is not needed. If during the operation of the block (on the main thread), an attempt is performed to perform a block, it would be blocked until the currently executing block is finished. At the end of the day, the result would be the same as if a context switch was performed, only faster. On the other hand, calling performBlock: will queue the block on an arbitrary queue, often executing on a background thread.

In the example above, since you performBlockAndWait:, your private queue context executes your block on the main thread, as does the main context block. In your second example, you schedule the block to run asynchronously, so it is executed on a background thread.

You should not judge a thread's queue by it's name. To see if you are on the main queue, you can use dispatch_get_current_queue() and test if it is equal to dispatch_get_main_queue().



来源:https://stackoverflow.com/questions/19439141/nsmanagedobjectcontexts-performblockandwait-not-executing-on-the-receivers-qu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!