在后台队列上保存临时托管对象上下文

时间:2013-10-29 01:01:59

标签: ios multithreading core-data grand-central-dispatch nsmanagedobjectcontext

根据Concurrency with Core Data Guide,您不应该在后台线程中保存NSManagedObjectContext,因为应用程序可以在保存完成之前退出,因为线程已分离。

如果我理解正确,那就意味着这样的事情是不正确的

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
    [tempContext performBlockAndWait:^{
         //Do some processing
        NSError* error;
        [tempContext save:&error];
    }];
});

我的第一直觉是在主队列完成时将其保存在主队列中,但是managedObjectContexts应该是线程安全的。以下是解决问题的方法还是有更好的解决方案?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
    [tempContext performBlockAndWait:^{
        //Do some processing
    }];
    dispatch_async(dispatch_get_main_queue(), ^{
        [tempContext performBlockAndWait:^{
            NSError* error;
            [tempContext save:&error];
        }];
    });
});

1 个答案:

答案 0 :(得分:1)

第一:

在你的第一个例子中:
[context save:...]应在上下文的performBlockAndWait:块中完成 此外,如果您使用的是背景上下文,则可以简单地调用其performBlock:方法,因为它已经使用GCD进行调度,因此它看起来像这样:

NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
[tempContext performBlock:^{
    //Do some processing
    NSError* error;
    [tempContext save:&error];
}];

其次:

“在后台线程中保存容易出错”(据我所知并理解)意味着:
您可以在后台保存,但如果应用程序退出(数据库仍然有效,或者可以回滚到部分保存前状态),则无法保证您调用的保存将运行完成。 /> ==>
如果使用后台保存,请不要假设在两次应用程序执行之间完成了保存操作。

第三(仅强调):
不要在没有performBlock:performBlockAndWait:的情况下使用私有队列上下文 ==>
你的第二个例子会导致意想不到的行为