【发布时间】:2013-08-23 22:49:15
【问题描述】:
我对@987654321@ 线程的理解是,它只能在创建它的线程上执行核心数据获取请求、删除等。有什么方法可以检查NSManagedObjectContext 是在哪个线程上创建的,或者在特定执行点当前线程是否是特定NSManagedObjectContext 的线程?
谢谢!
【问题讨论】:
标签: ios objective-c multithreading core-data thread-safety
我对@987654321@ 线程的理解是,它只能在创建它的线程上执行核心数据获取请求、删除等。有什么方法可以检查NSManagedObjectContext 是在哪个线程上创建的,或者在特定执行点当前线程是否是特定NSManagedObjectContext 的线程?
谢谢!
【问题讨论】:
标签: ios objective-c multithreading core-data thread-safety
我对 NSManagedObjectContext 线程的理解是,它只能在创建它的线程上执行核心数据获取请求、删除等。
这不是很准确。最好说上下文不能被多个线程或队列同时使用。处理此问题的常用方法是为每个线程/队列创建不同的上下文。也可以使用performBlock 和performBlockAndWait 方法在多个线程上使用上下文,同时保持上下文访问有效地单线程。
因此,上下文没有任何属于线程或队列的概念,线程也没有对在其上创建的上下文的任何引用。
如果您遵循每个线程或队列一个上下文的方法,您需要跟踪代码将在哪里运行并使用适当的上下文。例如,在使用 GCD 时,为特定的调度队列创建一个上下文,并且仅当您使用类似 dispatch_async 之类的东西在该队列上运行时才使用它。
如果您真的想将上下文与队列链接,您可以使用自己的数据结构从您正在使用的任何并发方案中查找上下文——通过当前的NSOperationQueue、调度队列或@987654325 @, 管他呢。这很少需要,但如果您找不到更好的技术,这是可能的。
【讨论】:
据我所知,你不能。至少不会太容易。为什么?使用-performBlock: - 它将在正确的线程上执行所有请求。
【讨论】:
抱歉,Tom Harrington,但实际上这根本不正确。虽然从技术上讲您可以这样做,但结果将是随机的,并且通常(根据我的经验)会导致竞争条件变得非常难以调试。
文档明确指出您应该使用上下文 PER 线程。事实上,即使是一些最好的框架(即 MagicalRecord)也以这种方式运行。 NSManagedObject 及其上下文不是线程安全的,但是 objectID 是。
要检查更改,您可以将更改保留到父上下文,也可以收听提供的通知。使用第二种方法,您需要读取要访问的项目的 objectID,然后从本地上下文再次请求它们。
阅读以下 Apple 文档以更好地了解其工作原理。
经过进一步研究,我发现一个文档最近一次更新是在过去几周内,尽管您对 performBlock 方法的看法是正确的,但它仍然声明您不应该在线程之间传递上下文。也许我误读了这个问题并迅速做出了回应。我最近一直在研究一个基于 CoreData 的大型应用程序,我知道我们遇到了很多与上下文和线程相关的问题,所以我回复得很快。 ;)
【讨论】:
The DOCs explicitly indicate that you should use a context PER thread 不准确。充其量,您指的是与限制模式相关的部分过时文档。大多数最近直接来自 Apple 的文档和建议都建议忽略所有线程并使用 performBlock 与托管对象上下文进行交互。
performBlock 方法之一中,因为这是核心数据提供的同步 API。 performBlock 不只是用于保存和合并。