在NSManagedObjectContext上嵌套执行performBlock:

8
当使用NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType类型的NSManagedObjectContext时,对同一个上下文进行嵌套调用performBlock是否安全?
[backgroundContext performBlock:^{
   NSFetchRequest *myRequest = ...;  
   __block NSArray *result= nil;
   [backgroundContext performBlockAndWait:^{
       results = [backgroundContext executeFetchRequest:myRequest error:NULL];
   }];
}];

这可能看起来很愚蠢,但我有一个现有的代码库,里面有很多帮助方法封装了executeFetchRequest调用。我不想假设调用者是否已经使用了performBlock。

-(void)updateObjects:(BOOL)synchronous
{
    if (YES == synchronous)
        [self fetchHelper];
    else
    {
        [backgroundContext performBlock:^{
             [self fetchHelper];
        }];
    }
}

-(NSArray*)fetchHelper
{
     [self.backgroundContext performBlockAndWait:^{
         //Fetch the objects...
         [self.backgroundContext executeFetchRequest: (...)];
     }];
}

我已经尝试过它并且它有效。但是我(吃了亏)学会了在使用核心数据和多线程时要非常小心。

1个回答

9
是的,performBlockAndWait是可重入的。直接引用自苹果的发布注释...
Core Data为NSManagedObjectContext类正式制定了并发模型,并提供了新选项。在创建上下文时,可以指定要使用的并发模式:线程限制、私有调度队列或主调度队列。NSConfinementConcurrencyType选项提供了与iOS 5.0之前版本相同的行为,并且是默认选项。对于使用队列关联创建的上下文,如果您的代码不是已在该队列上执行(对于主队列类型),或者不在performBlock...调用的范围内(对于私有队列类型),则在向上下文发送消息时必须使用performBlock:或performBlockAndWait:方法。在传递给这些方法的块中,可以自由地使用NSManagedObjectContext的方法。performBlockAndWait:方法支持API重入。performBlock:方法包含一个自动释放池,并在完成后调用processPendingChanges方法。

只是为了明确,OP在第二段代码中所做的是可以的吗?但如果两种方法都有“performBlock”,可能会导致问题?这是正确的看法吗? - hokkuk
1
那取决于你对“OK”的定义。我不会这样做。我的经验法则是,只有在特殊情况下才使用performBlockAndWait,并且我尽一切可能避免使用它。它很容易死锁(必须知道调用它的上下文,否则可能会死锁),而且它违反了FIFO原则(嵌套调用立即执行并“跳过”等待异步块的队列)。这在iOS8中的新异步获取中更为明显。 - Jody Hagins
@JodyHagins。关于performBlockAndWait和FIFO原则的小提示。当调用者在具有队列的CoreData上调用performBlockAndWait时,队列不会将新块放在所有其他异步排队项目的前面。调用线程只是等待其块执行,然后返回。到那时,所有其他异步块都已执行。当涉及嵌套的performBlockAndWait时,相同的原则会导致死锁。(这就像在主线程上调用dispatch_sync,而你正在主线程上运行一样)。但是,CoreData的performBlockAndWait已经被设计成可重入以避免死锁。 - Kris Subramanian
@KrisSubramanian - 也许现在是这样,但我向您保证,那时候或者仅仅一年前不是这样的。如果我有时间(可能性不大),我会使用最新的库运行一个实验 - 或者如果其他人想要运行测试,那也很好。 - Jody Hagins
@Shyam 是的,它会安排另一个异步任务。 - Jody Hagins
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接