具有私有并发类型的 NSManagedObjectContext 在主线程上执行块

Posted

技术标签:

【中文标题】具有私有并发类型的 NSManagedObjectContext 在主线程上执行块【英文标题】:NSManagedObjectContext with private concurrency type executes block on main thread 【发布时间】:2012-07-29 22:35:17 【问题描述】:

ios5 中,我有一个使用 NSPrivateQueueConcurrencyType 创建的 NSManagedObjectContext,如下所示:

self.moc = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease];
moc.parentContext = rootContext;

这在主线程上执行,但如果我正确理解了文档,那也没关系,因为 MOC 有自己的队列,对吧?

现在,有时我会执行一个获取请求,如下所示:

[self.moc performBlockAndWait:^()  // (1)
    NSError* err = nil;

    result = [self.moc executeFetchRequest:request error:&err];

    NSLog(@"%@ %@", [NSThread currentThread], [NSThread isMainThread]?@"MAIN":@"");
];

调用 (1) 也在主线程上调用。但我希望块内的获取请求在私有 MOC 线程上执行。到目前为止正确吗?

但是,如果我检查块内的当前线程,它实际上是主线程! NSLog 打印:

<NSThread: 0x6b10780>name = (null), num = 1 MAIN

检查线程转储可以确认这一点。

不应在主线程上执行 fetch,因为这偶尔会导致与其他一些正在运行的代码发生死锁。那么我在这里做错了什么?

【问题讨论】:

【参考方案1】:

好的,我仍然不完全确定这里的机制,即发布在上下文私有队列上的内容如何最终出现在主线程上。我怀疑它与同步执行块的 performBlockAndWait 有关。我重写了一些东西,所以现在一切都是异步完成的,并且块现在在其私有线程上执行。

感谢所有建议。

【讨论】:

重新阅读我上面的答案。没有私人 MOC 队列 - 你从未创建过它。 NSPrivateQueueConcurrencyType 标志只是告诉 Core Data 你想如何使用它——它不会为你创建队列。您在上面的代码中所做的一切都在主队列中。 我试图编辑上述错误信息,超时。我的更正:我的信息是 iOS 4 - 很抱歉造成混淆。无论如何,我认为正在发生的事情是 MOC 正在其队列上进行工作,并且为了方便您,将您发送回与您发送消息的同一线程上。因此,由于您要求它执行操作并等待它(performBlockAndWait),它在其线程上执行工作但阻塞主线程。您可以在此消息之前和之后记录并记录时间差以检验此假设。 感谢您的更正。我再次在文档中查找它,它明确指出在指定 NSPrivateQueueConcurrencyType 时“上下文创建并管理私有队列”。我怀疑你所描述的事情正在发生。无论如何,它现在工作正常。

以上是关于具有私有并发类型的 NSManagedObjectContext 在主线程上执行块的主要内容,如果未能解决你的问题,请参考以下文章

目标 c - 核心数据:无法调用 NSManagedObject 子类的私有方法

具有两个不同核心数据 NSManagedObject 实体的 NSTreeController

NSManagedObject 子类中的泛型类型

如何在 NSManagedObject 子类中使用 Transformable 属性作为其实际类型?

将 NSManagedObject 数组与另一个“对象”类型 Swift 2 的数组进行比较

“NSManagedObject”类的 NSManagedObject 必须具有有效的 NSEntityDescription