【问题标题】:Is there a way to figure out what thread an NSManagedObjectContext is on?有没有办法找出 NSManagedObjectContext 在哪个线程上?
【发布时间】:2013-08-23 22:49:15
【问题描述】:

我对@9​​87654321@ 线程的理解是,它只能在创建它的线程上执行核心数据获取请求、删除等。有什么方法可以检查NSManagedObjectContext 是在哪个线程上创建的,或者在特定执行点当前线程是否是特定NSManagedObjectContext 的线程?

谢谢!

【问题讨论】:

    标签: ios objective-c multithreading core-data thread-safety


    【解决方案1】:

    我对 NSManagedObjectContext 线程的理解是,它只能在创建它的线程上执行核心数据获取请求、删除等。

    这不是很准确。最好说上下文不能被多个线程或队列同时使用。处理此问题的常用方法是为每个线程/队列创建不同的上下文。也可以使用performBlockperformBlockAndWait 方法在多个线程上使用上下文,同时保持上下文访问有效地单线程。

    因此,上下文没有任何属于线程或队列的概念,线程也没有对在其上创建的上下文的任何引用。

    如果您遵循每个线程或队列一个上下文的方法,您需要跟踪代码将在哪里运行并使用适当的上下文。例如,在使用 GCD 时,为特定的调度队列创建一个上下文,并且仅当您使用类似 dispatch_async 之类的东西在该队列上运行时才使用它。

    如果您真的想将上下文与队列链接,您可以使用自己的数据结构从您正在使用的任何并发方案中查找上下文——通过当前的NSOperationQueue、调度队列或@987654325 @, 管他呢。这很少需要,但如果您找不到更好的技术,这是可能的。

    【讨论】:

    • 我实际上并不需要实现这个,我只是好奇。感谢您提供如此详尽的答案!
    【解决方案2】:

    据我所知,你不能。至少不会太容易。为什么?使用-performBlock: - 它将在正确的线程上执行所有请求。

    【讨论】:

      【解决方案3】:

      抱歉,Tom Harrington,但实际上这根本不正确。虽然从技术上讲您可以这样做,但结果将是随机的,并且通常(根据我的经验)会导致竞争条件变得非常难以调试。

      文档明确指出您应该使用上下文 PER 线程。事实上,即使是一些最好的框架(即 MagicalRecord)也以这种方式运行。 NSManagedObject 及其上下文不是线程安全的,但是 objectID 是。

      要检查更改,您可以将更改保留到父上下文,也可以收听提供的通知。使用第二种方法,您需要读取要访问的项目的 objectID,然后从本地上下文再次请求它们。

      阅读以下 Apple 文档以更好地了解其工作原理。

      https://developer.apple.com/library/ios/documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html


      经过进一步研究,我发现一个文档最近一次更新是在过去几周内,尽管您对 performBlock 方法的看法是正确的,但它仍然声明您不应该在线程之间传递上下文。也许我误读了这个问题并迅速做出了回应。我最近一直在研究一个基于 CoreData 的大型应用程序,我知道我们遇到了很多与上下文和线程相关的问题,所以我回复得很快。 ;)

      https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html

      【讨论】:

      • 我不确定你所说的 Tom 的帖子有什么问题。此外,您的声明The DOCs explicitly indicate that you should use a context PER thread 不准确。充其量,您指的是与限制模式相关的部分过时文档。大多数最近直接来自 Apple 的文档和建议都建议忽略所有线程并使用 performBlock 与托管对象上下文进行交互。
      • 你应该使用新的并发初始化器和 performBlock,这是真的。然而,这些新的 API 只解决了与跨上下文合并相关的问题。它们不会突然使上下文,甚至 NSManagedObject 的线程安全。所以重要的是每个线程仍然只使用 1 个上下文,然后按照您的建议,使用 performBlock 保存更改。
      • 也许我误解了你的意思。新的 API确实 使得使用 MOC 是线程安全的......就像使用任何同步 API 使得使用对象成为线程安全的一样。如果你使用 confinement API,你需要关心你在哪个线程上。否则,您应该完全忘记线程,并将每个访问都包装在 performBlock 方法之一中,因为这是核心数据提供的同步 API。 performBlock 不只是用于保存和合并。
      • 完全正确.. 说实话,我想我忘记了我的观点哈哈.. 但是是的,这就是我想说的,以确保所有访问都在 performBlock 内完成,否则你可以结束解决胎面安全问题。 ;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 2012-10-17
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多