我已经阅读了 Marcus Zarra 在他的 Core Data 书中关于多线程的一章,并且相当仔细地查看了他的示例代码。但是他的代码和我在其他地方找到的其他代码似乎都集中在不需要相互了解的后台进程中。这些示例适用于导入树结构 - 但它们没有解决更一般(复杂)结构的导入,例如有向无环图。
就我而言,我正在尝试解析 C++ 类层次结构,并希望使用尽可能多的 NSOperations。我想为每个遇到的类创建一个 NSManagedObject 实例,并且我想在保存一个时合并不同的 NSManagedObjectContexts。
顺便说一句:我能够使用单个 NSOperation 来迭代文件并一次解析一个。在此实现中,在主线程的 MOC 上调用 -mergeChangesFromContextDidSaveNotification: 的 -mergeChanges: 方法运行良好。
但理想情况下,我会让一个 NSOperation 遍历源文件并生成 NSOperation 来解析每个文件。我尝试了几种方法 - 但似乎无法做到正确。最有希望的是让每个 NSOperation 观察 NSManagedObjectContextDidSaveNotification。使用 -mergeChanges: 看起来像这样:
- (void) mergeChanges:(NSNotification *)notification
{
// If locally originated, then trigger main thread to merge.
if ([notification object] == [self managedObjectContext])
{
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
return;
}
// If not locally originated, then flag need to merge with in this NSOperation's thread.
[self setNeedsToMerge:YES];
[self setMergeNotification:notification];
}
本质上,解析 NSOperation 的 main() 会定期检查 ivar 'needsToMerge'。如果是真的,那么 -mergeChangesFromContextDidSaveNotification: 在本地 MOC 上被调用并缓存了 NSNotification。然后 needsToMerge 被重置。如果通知来自本地,则主线程被告知在其 MOC 上执行 -mergeChangesFromContextDidSaveNotification:。
我确信这有一个很好的理由为什么这不起作用以及为什么我得到这个:
警告:取消调用 - 当前线程堆栈上的 objc 代码会使这不安全。
我还尝试使用 NSPeristentStoreCoordinator 的锁来控制访问 - 但如果它在调用 NSManagedObjectContext 的 -save: 方法期间被持有,这是有问题的,因为 -save: 将通知感兴趣的观察者保存事件和 -mergeChangesFromContextDidSaveNotification: 似乎阻止尝试获取PSC的锁。
似乎这应该容易得多。