NSManagedObjectContext的performBlockAndWait:不在接收者的队列上执行

时间:2013-10-17 23:39:42

标签: iphone ios objective-c core-data grand-central-dispatch

我注意到NSManagedObjectContext可能NSMainQueueConcurrencyTypeperformBlockAndWait:并且在接收者(主)队列以外的队列上执行阻止。

例如,如果我的parentContext类型为childContext且{{1} parentContext,则以下代码会导致我NSMainQueueConcurrencyType执行childContext队列中的阻止类型为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
    }];
}];

相反,以下代码按预期工作 - 我的parentContext执行主队列上的块:

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

这是预期的行为吗?自从文档陈述"performBlockAndWait: synchronously performs a given block on the receiver’s queue."

以来,我当然会感到困惑

1 个答案:

答案 0 :(得分:3)

您不应该担心执行哪些线程块。 performBlock:performBlockAndWait:方法保证的是线程安全性。因此,从主线程调用performBlockAndWait:并不意味着会有一个上下文切换到后台线程 - 它非常昂贵而且不需要。如果在块的操作期间(在主线程上),执行尝试以执行块,则它将被阻塞,直到当前正在执行的块完成。在一天结束时,结果将与执行上下文切换的结果相同,但速度更快。另一方面,调用performBlock:会将块排在任意队列上,通常在后台线程上执行。

在上面的示例中,由于您performBlockAndWait:,您的私有队列上下文在主线程上执行您的块,主上下文块也是如此。在第二个示例中,您将调度块以异步方式运行,因此它将在后台线程上执行。

你不应该用它的名字判断一个线程的队列。要查看您是否在主要队列中,可以使用dispatch_get_current_queue()并测试它是否等于dispatch_get_main_queue()