总结:在多线程场景中调用[myMOC mergeChangesFromContextDidSaveNotification:notification]
时,我的应用程序已挂起。
详细情况如下:
我的应用从服务器下载了大量数据,并在首次启动时将其存储在Core Data中。它有几个部分。解析整个过程需要几秒钟,大部分时间都花在了两个块上。所以为了加快速度,我将这两个块并行化了。这就是它的样子:
NSArray *arr = [self parseJsonData:downloadedNSData]; //turns NSData into JSON array
//using NSJSONSerialization
NSMutableArray __block *first = [[NSMutableArray alloc]init];
NSMutableArray __block *second = [[NSMutableArray alloc]init];
//put half of arr in first and half in second with a loop
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dipatch_group_create();
dispatch_group_async(group, queue, ^
{
for (id element in first)
{
[MyDataClass parseData:element]; //create NSManagedObject subclass, save
}
[self saveContext];
});
dispatch_group_async(group, queue, ^
{
for (id element in second)
{
[MyDataClass parseData:element]; //create NSManagedObject subclass, save
}
[self saveContext];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
[self saveContext]
在MOC上调用save
。这当然是在多个线程上完成的,所以我需要为每个线程创建一个单独的ManagedObjectContext
。这是通过在此对象(self
)上通过属性公开MOC来实现的,该对象维护NSMutableDictionary
个线程名称(在description
上调用NSThread
)到{{1} }秒。访问时,如果没有NSManagedObjectContext
的MOC,它会创建一个新的MOC,将其添加到字典中并存储它。创建每个MOC时,我订阅其更改通知:
[NSThread currentThread]
在NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification object:createdMOC];
中,我遍历我的上下文字典并在所有这些字典上调用mergeChanges
,除了正在发生的线程的那个。更具体地说,我使用mergeChangesFromContextDidSaveNotification
让每个MOC在为其创建的线程上执行此操作。
我还使用[performSelector:onThread:withObject:waitUntilDone:]
和NSLock
方法围绕[myMOC save]
锁定。如果我没有锁定那些,我得到“Cocoa error 133020”,apparently表示合并更改时出错。
所以,这就是我的日志记录告诉我的事情:
那么,为什么在合并变化时它会挂起?有没有更好的方法来处理这种情况?
更新:我尝试在mergeChanges
电话周围使用[persistentStoreCoordinator lock]
而不是仅使用[MOC save]
锁定,但无济于事。我还尝试在其中一个NSLock
来电中调用[NSThread sleepForTimeInterval:2]
之前添加[self saveContext]
,但没有帮助。
更新2:也许这里更好的问题是我遇到合并冲突的原因(可可错误133020)。这是预期的吗?我是否正确进行合并(合并到除一个保存之外的所有上下文)?
更新3:我发布了another question来解决我正在进行多线程处理的更大背景。
答案 0 :(得分:0)
当您创建NSManagedObject
子类时,您将其插入到上下文中,因此您只能在属于上下文的队列/线程上执行此操作。
在上下文中调用-save
同样如此。
在您的代码中,我认为您正在插入两个对象 - 每个对象都在自己的线程上。那不行。
答案 1 :(得分:-1)
我发布了this question更好地记录我的情况。我认为目前这个问题的范围有点狭窄。