我正在使用苹果的并发核心数据调试器.
-com.apple.CoreData.ConcurrencyDebug 1
有时候我得到__Multithreading_Violation_AllThatIsLeftToUsIsHonor__,即使我几乎肯定线程没有被违反.
这是发生异常的代码的一部分(代码是扩展NSManagedobject的协议的一部分):
public static func find(arrayBy predicate: nspredicate,sort: [NSSortDescriptor] = [],limit: Int? = nil) -> [Self] { let fetchRequest = NSFetchRequest<Self>(entityName: "\(Self.self)") fetchRequest.predicate = predicate fetchRequest.sortDescriptors = sort do { return try Context.current.fetch(fetchRequest) // Exception!!! } catch let error { Logger.fatal("Failed to perform fetch: \(error)") return [] } }
代码在上下文的执行:块中执行.
这里是线程信息:
和调试器信息来确认执行是否正确执行NSManagedContext:
(lldb) po Context.current <StoreContext: 0x7f854b556610>
实体名称被成功提取:
po fetchRequest.entityName! "Position"
谓词由纯String对象构成(根本不使用任何托管对象):
(lldb) po fetchRequest.predicate! ANY employees.company.id == "282372"
在这种情况下,完全不使用排序描述符:
po fetchRequest.sortDescriptors! 0 elements
限制完全被忽略.
我失踪了什么有人有什么想法吗?
编辑:
为了澄清,Context.current是在调度块之前设置的:
Context.current = managedobjectContext managedobjectContext.performAndWait { //... }
您可以在截图上看到Thread 13在Queue上运行:NSManagedobject 0x7f854b556610(serial).而且,当异常发生时Context.current返回< StoreContext:0x7f854b556610> ;.通过查看内存地址,很容易得出结论块正在正确的队列中执行.
解决方法
将“当前”背景环境存储在全局状态是不好的做法.我不能指出你的代码在哪里搞错了,但是当涉及多线程时,全局状态会发生意想不到的事情.更改您的查找功能以接受上下文作为参数.这将避免使用任何全局状态,并且可能会解决您的问题.