1

两天以来,我一直在尝试让 Core Data 使用多个线程。我尝试了使用 NSOperations 的标准线程限制方法、合并通知、使用 objectWithId、每个线程的上下文字典,但我仍然遇到奇怪的死锁、不一致的异常和一堆其他讨厌的东西。这让我发疯......此外,当两个线程都可能对共享持久存储进行更改时,我找不到一个关于如何在两个线程中管理上下文的示例或解释......

我尝试使用新的 iOS 5 方法,这应该更容易,但仍然出现错误。第一个问题是保存上下文时的死锁。我删除了所有不必要的代码,并且在足够快地执行此代码时仍然会出现死锁(通过快速点击按钮):

    NSManagedObjectContext *context = [StoreDataRetriever sharedRetriever].managedObjectContext;

    for (int i = 0; i < 5; i++) {            
        NSError *error = nil;
        NSLog(@"Main thread: %@, is main? %d", [NSThread currentThread], [NSThread isMainThread]);
        BOOL saveOK = [context save:&error];

        if (!saveOK) {
            NSLog(@"ERROR!!! SAVING CONTEXT IN MAIN");
        }

        [context performBlock:^{

            NSLog(@"Block thread: %@", [NSThread currentThread]);

            NSError *error = nil;
            BOOL savedOK = NO;

            savedOK = [context save:&error]; 

            if (!savedOK) {
                NSLog(@"ERROR!!! SAVING CONTEXT IN BLOCK");
            }
        }];
    }

数据库没有其他更改,什么都没有,只是保存上下文。这段代码有什么问题?它应该是什么样子?

注意:[StoreDataRetriever sharedRetriever].managedObjectContext 是在 appDelegate 中使用 initWithConcurrencyType:NSPrivateQueueConcurrencyType 创建的。

4

1 回答 1

2

这段代码是怎么回事?您正在将上下文同步保存在线程上,然后安排在上下文专用队列上保存。5次。所以基本上,你很可能有两个保存操作,一个同步和一个异步,相互冲突。

这显然是一个问题。您不应该使用该队列之外的私有队列保存上下文。如果上下文队列上没有计划块,它将与当前上下文实现一起使用。但这仍然是错误的。

…
for (int i = 0; i < 5; i++) {            
    NSLog(@"Main thread: %@, is main? %d", [NSThread currentThread], [NSThread isMainThread]);
    __block NSError *error = nil;
    __block BOOL saveOK = YES;
[context performBlockAndWait: ^{
    saveOK = [context save: &error];
}];

    if (!saveOK) {
        NSLog(@"ERROR!!!");
    }
    …

使用该代码,您可以在同一个线程上同步执行保存操作 - 感谢 GCD - 节省了上下文切换和同步内容,并且没有任何同时在该上下文上运行两个操作的风险。

使用 NSMainQueueConcurrencyType 时也适用相同的规则,但有一个例外。该队列仅绑定到主线程和主线程。您可以使用带有 performBlock 和 performBlockAndWait(如 NSPrivateQueueConcurrencyType)的任何线程的主队列在上下文中调度块,并且(例外:)您可以直接在主线程上使用上下文。

NSConfinementConcurrencyType 将上下文绑定到特定线程,您不能使用 GCD 或块来处理这样的上下文,只能使用绑定的线程。到目前为止,几乎没有理由使用该并发模型。如果必须,请使用它,但如果您不是绝对必须,请不要。


编辑

这是一篇关于多上下文设置的非常好的文章:http: //www.cocoanetics.com/2012/07/multi-context-coredata/

于 2012-07-20T22:03:50.880 回答