NSManagedObjectContext通过通知中心问题在多个线程上保存/合并

时间:2011-05-04 20:04:02

标签: objective-c multithreading ios core-data nsmanagedobjectcontext

这更像是为什么这项工作并没有什么问题......

我在多个线程上使用CoreData。我有两个主线程产生的线程,它们都执行类似的调用:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:nil 
                                                    usingBlock:^(NSNotification *saveNotification) {
                                                        dispatch_async(dispatch_get_main_queue(), ^{
                                                            [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                        });
                                                    }];
    [secondManagedObjectContext save:nil];


    [notificationCenter removeObserver:observerObject
                                  name:NSManagedObjectContextDidSaveNotification 
                                object:syncManagedObjectContext];

这似乎工作正常,但之前我在通知中心这样做并遇到了一些问题:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:[NSOperationQueue mainQueue]
                                                    usingBlock:^(NSNotification *saveNotification) {
                                                        [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                    }];

这有时会起作用,但有时候XCode会在启动时暂停并在调用时放下一个绿色断点,只列出线程及其编号,但没有错误。 (注意:只有在我生成两个或多个线程时才会出现此问题。)

罪魁祸首似乎是:[NSOperationQueue mainQueue],但我似乎无法弄清楚为什么它会使线程暂停。我能够在调试器中继续按下并继续...但我不明白为什么它以这种方式运行。

我认为我做错了什么,我担心我的新方式可能只是一个黑客。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

我认为第一个因为异步调度而起作用。如果没有这个,通知中心将暂停,直到任何特定通知完成。你得到的问题听起来像一个典型的停顿,代码只是暂停而没有错误,直到调试器最终超时。

答案 1 :(得分:0)

不确定这是否有帮助,但在队列中没有nil的情况下尝试使用通用队列。看一下apple docs中的接待员设计模式。

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];

答案 2 :(得分:0)

第一个代码示例中的合并在主线程上正确分派,主线程很可能也是创建moc的线程。

在第二个示例中,如果通知是在bg线程上发出的,则合并将在后台线程上执行(通知回调总是在发布通知的同一线程上调用)。

BTW,我现在宁愿使用NSManagedObjectContext自己的performBlock:方法(> = iOS 5),而不是使用主队列。在带有ARC的iOS5上,此代码归结为:

__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [weakSelf.moc performBlock:^{
        [weakSelf.moc mergeChangesFromContextDidSaveNotification:note];
    }];
}];