在异步操作中使用 Core Data
Using Core Data in an asynchronous operation
我有一个 iOS 同步进程分解为一系列异步 NSOperation 子类。这些被分解为进行大量处理的那些和那些依赖网络的。但他们中的大多数人也用核心数据做事。
我不确定如何在操作中执行核心数据操作。
这里有几个简单的例子......我的真实代码做了几次进出数据库上下文的切换。它还使用 @synchronize(self){}
.
NSManagedContext *context = [self newContextFromParent];
__block NSString *someValue;
[context performBlockAndWait:^{
// fetch someValue from Core Data
}];
[self doMoreWorkWithValue:someValue];
[context performBlockAndWait:^{
NSError *e;
if ([context hasChanges]) {
[context saveChanges:&e];
}
}];
从表面上看,这似乎是个好方法,但根据我在 performBlockAndWait:
中所做的工作,这里可能会出现死锁。
一般来说,我喜欢在我的代码中避免使用 performBlockAndWait:
,而是使用 performBlock:
。
[context performBlock:^{
NSString *someValue = @""; // fetch someValue from Core Data
[backgroundQueue addOperationWithBlock:^{
[self doMoreWorkWithValue:someValue withCompletion:^{
[context performBlock:^{
NSError *e;
if ([context hasChanges]) {
[context saveChanges:&e];
}
}];
}];
}];
}];
不过,通过这种方法,我已经将我的处理从分配给我的线程转移到 backgroundQueue
决定 运行 我的进程的任何线程,我不确定是什么更好的方法是。
如果我在主操作中捕获 [NSOperation currentQueue]
并改为添加到它,我已将我的块添加到队列的末尾。我真正想要的是恢复。
我应该在这里使用什么方法?
你的第一种方法是我会使用的方法。不过,您提到了对 performBlockAndWait:
内部死锁的担忧。您是否担心调用另一个本身可能使用 performBlockAndWait:
的方法?如果是这样,不用担心; performBlockAndWait:
使用 re-entrantly 是明确安全的。即:此代码是安全的(尽管显然是人为设计的):
[context performBlockAndWait:^{
[context performBlockAndWait:^{
// fetch someValue from Core Data
}];
}];
如果死锁问题与 Core Data 无关,那么您似乎在 doMoreWorkWithValue:
内部也有同样多的死锁风险,对吗?
我有一个 iOS 同步进程分解为一系列异步 NSOperation 子类。这些被分解为进行大量处理的那些和那些依赖网络的。但他们中的大多数人也用核心数据做事。
我不确定如何在操作中执行核心数据操作。
这里有几个简单的例子......我的真实代码做了几次进出数据库上下文的切换。它还使用 @synchronize(self){}
.
NSManagedContext *context = [self newContextFromParent];
__block NSString *someValue;
[context performBlockAndWait:^{
// fetch someValue from Core Data
}];
[self doMoreWorkWithValue:someValue];
[context performBlockAndWait:^{
NSError *e;
if ([context hasChanges]) {
[context saveChanges:&e];
}
}];
从表面上看,这似乎是个好方法,但根据我在 performBlockAndWait:
中所做的工作,这里可能会出现死锁。
一般来说,我喜欢在我的代码中避免使用 performBlockAndWait:
,而是使用 performBlock:
。
[context performBlock:^{
NSString *someValue = @""; // fetch someValue from Core Data
[backgroundQueue addOperationWithBlock:^{
[self doMoreWorkWithValue:someValue withCompletion:^{
[context performBlock:^{
NSError *e;
if ([context hasChanges]) {
[context saveChanges:&e];
}
}];
}];
}];
}];
不过,通过这种方法,我已经将我的处理从分配给我的线程转移到 backgroundQueue
决定 运行 我的进程的任何线程,我不确定是什么更好的方法是。
如果我在主操作中捕获 [NSOperation currentQueue]
并改为添加到它,我已将我的块添加到队列的末尾。我真正想要的是恢复。
我应该在这里使用什么方法?
你的第一种方法是我会使用的方法。不过,您提到了对 performBlockAndWait:
内部死锁的担忧。您是否担心调用另一个本身可能使用 performBlockAndWait:
的方法?如果是这样,不用担心; performBlockAndWait:
使用 re-entrantly 是明确安全的。即:此代码是安全的(尽管显然是人为设计的):
[context performBlockAndWait:^{
[context performBlockAndWait:^{
// fetch someValue from Core Data
}];
}];
如果死锁问题与 Core Data 无关,那么您似乎在 doMoreWorkWithValue:
内部也有同样多的死锁风险,对吗?