Core data 在串行NSOperationQueue上初始化NSManagedObjectContext
我有一个Core data 在串行NSOperationQueue上初始化NSManagedObjectContext,core-data,nsmanagedobjectcontext,nsoperation,nsoperationqueue,Core Data,Nsmanagedobjectcontext,Nsoperation,Nsoperationqueue,我有一个NSOperationQueue,其中添加了一些NSBlockOperations,其中包括blockOperations A和B。NSOperationQueue的maxConcurrencyOperationCount为1 阻塞操作B取决于A是否完成。在每个块操作中,我调用一个方法,该方法反过来调用另一个方法,该方法初始化一个新的NSManagedObjectContext(使用singleton中的persistentStoreCoordinator),我使用该方法创建对象并将其添
NSOperationQueue
,其中添加了一些NSBlockOperations
,其中包括blockOperations A和B。NSOperationQueue
的maxConcurrencyOperationCount
为1
阻塞操作B取决于A是否完成。在每个块操作中,我调用一个方法,该方法反过来调用另一个方法,该方法初始化一个新的NSManagedObjectContext
(使用singleton中的persistentStoreCoordinator),我使用该方法创建对象并将其添加到核心数据数据库中。前面提到的A和B中的第二个方法调用调用的代码如下所示(每个方法调用的代码略有不同):
saveContext:
代码如下所示:
NSError *error = nil;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
}
在花了大量时间阅读苹果公司关于核心数据并发性、NSOperation等方面的文档之后,我仍然不确定我使用NSManagedObjectContext所做的是否是线程安全的,并且通常认为是可以的?如果能澄清和/或表明我应该采取不同的做法,我将不胜感激。如果您需要查看更多代码,请询问
提前感谢。上下文的问题是它只能在单个线程中访问。设置MaxConcurrencyOperationCount并不能保证这一点。另一种方法是将上下文设置为“thread”变量,在使用上下文的每个线程字典中存储上下文 例:
上下文的问题是,它只能在单个线程中访问。设置MaxConcurrencyOperationCount并不能保证这一点。另一种方法是将上下文设置为“thread”变量,在使用上下文的每个线程字典中存储上下文 例:
您所做的不是线程安全的。
如果决定为每个操作创建一个上下文,最好使用限制并发类型:
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
这样,您就不需要更改当前代码中的任何内容
如果要将上下文与NSPrivateQueueConcurrencyType
一起使用,则必须通过performBlock:
或performBlockAndWait:
访问该上下文中的对象:[managedObjectContext performBlockAndWait:^{//wait is used as to not end the operation before this code is executed
for (NSDictionary *articleDictionary in array) {
if (![Article articleExistsWithIDInDictionary:articleDictionary
inContext:managedObjectContext])
{
[Article articleFromDictionary:articleDictionary
inContext:managedObjectContext];
}
}
}];
对于你的情况,我可能会选择我的第一个解决方案。综上所述,您可以简单地使用“专用队列”上下文作为串行队列(只要您按照需要执行的顺序向其添加块操作)。
上下文
performBlock:
方法将对块进行排队,并针对添加该上下文以在后台执行的其他块串行执行它://add this to your CoreDataController
context = [[CoreDataController sharedCoreDataController] serialExecutionBGContext];
[context performBlock:^{ //your block operation code1}];
[context performBlock:^{ //your block operation code2}];
这将在后台连续执行代码1和代码2。通过这种方式,您可以节省分配新上下文的开销,并且可以从该上下文完成的缓存中获益。
您可能希望不时重置此上下文,以便它不会因获取的对象而膨胀。您所做的不是线程安全的。
如果决定为每个操作创建一个上下文,最好使用限制并发类型:
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
这样,您就不需要更改当前代码中的任何内容
如果要将上下文与NSPrivateQueueConcurrencyType
一起使用,则必须通过performBlock:
或performBlockAndWait:
访问该上下文中的对象:[managedObjectContext performBlockAndWait:^{//wait is used as to not end the operation before this code is executed
for (NSDictionary *articleDictionary in array) {
if (![Article articleExistsWithIDInDictionary:articleDictionary
inContext:managedObjectContext])
{
[Article articleFromDictionary:articleDictionary
inContext:managedObjectContext];
}
}
}];
对于你的情况,我可能会选择我的第一个解决方案。综上所述,您可以简单地使用“专用队列”上下文作为串行队列(只要您按照需要执行的顺序向其添加块操作)。
上下文
performBlock:
方法将对块进行排队,并针对添加该上下文以在后台执行的其他块串行执行它://add this to your CoreDataController
context = [[CoreDataController sharedCoreDataController] serialExecutionBGContext];
[context performBlock:^{ //your block operation code1}];
[context performBlock:^{ //your block operation code2}];
这将在后台连续执行代码1和代码2。通过这种方式,您可以节省分配新上下文的开销,并且可以从该上下文完成的缓存中获益。
您可能需要不时重置此上下文,这样它就不会因为获取的对象而变得臃肿。Hi Dan,谢谢您提供了非常翔实的答案。你能澄清一下“重置此上下文”的含义吗?NSManagedObjectContext上是否有重置方法?另外,如果按顺序执行
performBlock:
,则performBlock:
和performBlockAndWait:
之间有什么区别?是的,NSManagedObjectContext
上有一个reset
方法,可以将上下文中断获取的对象绑定到上下文。当您不再需要在上下文中获取现有数据,但仍希望保留上下文时,这是回收内存的一种好方法performBlock
不是串行执行的,它串行地对执行块进行排队,它是异步执行的,不阻塞当前线程(与它的andWait
对应线程不同)。通常情况下,一个上下文会对其自身串行执行其执行的块。Hi Dan,您说过“一个context performBlock:方法会对该块进行排队,并对添加了该上下文以在后台执行的其他块串行执行它:”但我在文档中找不到这一点。您在哪里读到队列是串行的?通常,NSOperationQueue默认情况下不是串行的,我们必须写入“queue.maxConcurrentOperationCount=1”以使其串行。谢谢。@superpuccio我不确定它是否能在官方文档中找到,但我能找到上下文使用串行队列的状态Hi Dan,谢谢你提供了非常翔实的答案。你能澄清一下“重置此上下文”的含义吗?NSManagedObjectContext上是否有重置方法?另外,如果按顺序执行performBlock:
,则performBlock:
和performBlockAndWait:
之间有什么区别?是的,NSManagedObjectContext
上有一个reset
方法,使上下文拒绝获取对象