0

根据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];
        }];
    });
});
4

1 回答 1

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];
}];

第二:

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

第三(只是强调):
不要使用没有performBlock:performBlockAndWait:
==>的私有队列上下文
您的第二个示例将导致意外行为

于 2013-10-29T05:30:18.980 回答